Objective-C:如何为TabBarController正确设置didSelectViewController方法,以便每次点击VC时都可以刷新VC [英] Objective-C: How to properly set didSelectViewController method for TabBarController, so I can refresh the VC everytime it is tapped

查看:73
本文介绍了Objective-C:如何为TabBarController正确设置didSelectViewController方法,以便每次点击VC时都可以刷新VC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图完成

tabbaritem上点击,它将调用tabbaritem VC上的相应方法.

问题

当我点击tabbaritem2时,它将调用tabbaritem2上的didSelectViewController,然后调用相应的方法.然后,当我点击tabbaritem3时,它仍会调用tabbaritem3上的didSelectViewController及其相应的方法.

但是当我切换回并点击tabbaritem2时.它仍然会调用tabbaritem3上的didSelectViewController而不是tabbaritem2上的didSelectViewController,并且相应的方法不再起作用

问题无间断

中断问题

问题

如何正确设置didSelectViewController方法,以便在点击tabbaritem时分别调用并加载该方法?

代码

MyTabBarController.m(我需要在这里做点什么吗?)

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSLog(@"didSelectViewController... ");

   // if ([viewController isKindOfClass:[UINavigationController class]]) {
   //      [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
   // }

    //=== I tried the following but it is not loading the method=====================
    //if ([viewController isKindOfClass:[ClassNavigationController class]]) {   // Here newViewController is the controller where the webview reload happens.
      //  [[[Classes alloc] init] reloadWebViewData];  // We create and instance for the new controller and call the delegate method where the reload works.
    //}

    //if (viewController == [tabBarController.viewControllers objectAtIndex:2]){
     //   [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
     //   [[[Classes alloc] init] LoadClasses];

    //}else if (viewController == [tabBarController.viewControllers objectAtIndex:3]){

      //  [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
      //  [[[Gym alloc] init] handleRefreshGym:nil];

    //}else{
        //=== The following code will make viewWillAppear load on each tab bar item
        //=== Without it, tapping on new tab bar item will not load viewWillAppear
      //  [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
    //}
    //=================================================================================
}

Classes.m

- (void)viewDidLoad {

    [super viewDidLoad];

    UITabBarController *tabBarController = (UITabBarController*)[UIApplication sharedApplication].keyWindow.rootViewController ;

    [tabBarController setDelegate:self];

}

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

    NSLog(@" Classes Called ");

    if (viewController == [tabBarController.viewControllers objectAtIndex:2])
    {
        [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
        [self handleRefresh:nil];

    }else{
        [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
    }

}

Gym.m

    - (void)viewDidLoad {

    [super viewDidLoad];

    UITabBarController *tabBarController1 = (UITabBarController*)[UIApplication sharedApplication].keyWindow.rootViewController ;

    [tabBarController1 setDelegate:self];

}

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

    NSLog(@" Gym Called ");

    if (viewController == [tabBarController.viewControllers objectAtIndex:3])
    {
        [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
        [self handleRefreshGym:nil];

    }else{
        [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
    }

}

MyStoryBoard

解决方案

因此TabBarController一次只能有一个委托.在您发布的代码中,您要在viewDidLoad的每个各自的视图控制器生命周期方法中设置tabBarController.delegate = self(在第一次加载视图时调用一次).因此,无论要加载的最后一个视图控制器都是最终的tabBarControllerDelegate.

这是一个非常简单的示例,以说明我的意思:

FirstViewController

#import "FirstViewController.h"

@interface FirstViewController () <UITabBarControllerDelegate>

@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tabBarController.delegate = self;
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"Who's my tab bar controller delegate = %@", self.tabBarController.delegate);
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSLog(@"Delegate called on %@", NSStringFromClass([self class]));
}


@end

SecondViewController

#import "SecondViewController.h"

@interface SecondViewController () <UITabBarControllerDelegate>

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tabBarController.delegate = self;
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"Who's my tab bar controller delegate = %@", self.tabBarController.delegate);
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSLog(@"Delegate called on %@", NSStringFromClass([self class]));
}

@end

如果我运行此程序并首先选择FirstViewController的选项卡,然后选择SecondViewController的选项卡,然后返回选择FirstViewController的选项卡,这是我得到的日志结果:

First Tab Selected:
Who's my tab bar controller delegate = <FirstViewController: 0x7ff9eb406970>
Delegate called on FirstViewController

Second Tab Selected:
Who's my tab bar controller delegate = <SecondViewController: 0x7fa33ac0a540>
Delegate called on FirstViewController (this is still FirstViewController here because the tab bar selection occurred prior to setting the SecondViewController to the tabBarControllerDelegate)

First Tab Selected:
Who's my tab bar controller delegate = <SecondViewController: 0x7fa33ac0a540>
Delegate called on SecondViewController

Second Tab Selected:
Who's my tab bar controller delegate = <SecondViewController: 0x7fa33ac0a540>
Delegate called on SecondViewController

...
 and it continues on that the SecondViewController will remain the delegate

所以我的建议是使用另一种模式,该模式仅维护一个协调器来处理TabBarDelegation.

根据您对其他建议的评论进行编辑

iOS中一个相当标准的习惯用法是从服务器加载一次数据(通常是在各个视图控制器的viewDidLoad中,然后将其存储),然后具有刷新控件,该控件允许用户根据命令刷新数据: https: //medium.com/ios-os-x-development/ios-tips-pull-to-refresh-in-少于30秒-ef884520f0df 如果您确实需要标签栏委托来做某事对于每个视图控制器选择,我建议有一个中心对象,它是唯一的选项卡栏委托,并让它根据通过委托方法tabBarController:didSelectViewController:传入的视图控制器来处理要执行的任务. >

Trying to accomplish

Tap on the tabbaritem and it will called the respective method on the tabbaritem VC.

Issue

When I tap on tabbaritem2 it will call didSelectViewController on tabbaritem2 and then the respective method. Then when I tap on tabbaritem3it will still call the didSelectViewController on tabbaritem3 and the respective method.

But when I switch back and tap on tabbaritem2. It will still call the didSelectViewController on tabbaritem3 and not didSelectViewController on tabbaritem2 and the respective method doesn't work anymore

The issue without break

The issue with break

Question

How to properly set up the didSelectViewController method so that when tabbaritem is tapped it will call and load the method respectively?

Code

MyTabBarController.m (Do I need to do something here?)

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSLog(@"didSelectViewController... ");

   // if ([viewController isKindOfClass:[UINavigationController class]]) {
   //      [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
   // }

    //=== I tried the following but it is not loading the method=====================
    //if ([viewController isKindOfClass:[ClassNavigationController class]]) {   // Here newViewController is the controller where the webview reload happens.
      //  [[[Classes alloc] init] reloadWebViewData];  // We create and instance for the new controller and call the delegate method where the reload works.
    //}

    //if (viewController == [tabBarController.viewControllers objectAtIndex:2]){
     //   [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
     //   [[[Classes alloc] init] LoadClasses];

    //}else if (viewController == [tabBarController.viewControllers objectAtIndex:3]){

      //  [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
      //  [[[Gym alloc] init] handleRefreshGym:nil];

    //}else{
        //=== The following code will make viewWillAppear load on each tab bar item
        //=== Without it, tapping on new tab bar item will not load viewWillAppear
      //  [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
    //}
    //=================================================================================
}

Classes.m

- (void)viewDidLoad {

    [super viewDidLoad];

    UITabBarController *tabBarController = (UITabBarController*)[UIApplication sharedApplication].keyWindow.rootViewController ;

    [tabBarController setDelegate:self];

}

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

    NSLog(@" Classes Called ");

    if (viewController == [tabBarController.viewControllers objectAtIndex:2])
    {
        [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
        [self handleRefresh:nil];

    }else{
        [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
    }

}

Gym.m

    - (void)viewDidLoad {

    [super viewDidLoad];

    UITabBarController *tabBarController1 = (UITabBarController*)[UIApplication sharedApplication].keyWindow.rootViewController ;

    [tabBarController1 setDelegate:self];

}

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

    NSLog(@" Gym Called ");

    if (viewController == [tabBarController.viewControllers objectAtIndex:3])
    {
        [(UINavigationController *)viewController popToRootViewControllerAnimated:YES];
        [self handleRefreshGym:nil];

    }else{
        [(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
    }

}

MyStoryBoard

解决方案

So the TabBarController can only have one delegate at a time. In the code you posted you're setting the tabBarController.delegate = self in each respective view controllers lifecycle method of viewDidLoad (called once when the view is first loaded). So whatever the last view controller is to load will be the final tabBarControllerDelegate.

Here's a very simple example to show what I mean:

FirstViewController

#import "FirstViewController.h"

@interface FirstViewController () <UITabBarControllerDelegate>

@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tabBarController.delegate = self;
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"Who's my tab bar controller delegate = %@", self.tabBarController.delegate);
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSLog(@"Delegate called on %@", NSStringFromClass([self class]));
}


@end

SecondViewController

#import "SecondViewController.h"

@interface SecondViewController () <UITabBarControllerDelegate>

@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tabBarController.delegate = self;
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"Who's my tab bar controller delegate = %@", self.tabBarController.delegate);
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSLog(@"Delegate called on %@", NSStringFromClass([self class]));
}

@end

If I run this and start by selecting the FirstViewController's tab, then select the SecondViewController's tab, then go back to selecting the FirstViewController's tab this is the log result I get:

First Tab Selected:
Who's my tab bar controller delegate = <FirstViewController: 0x7ff9eb406970>
Delegate called on FirstViewController

Second Tab Selected:
Who's my tab bar controller delegate = <SecondViewController: 0x7fa33ac0a540>
Delegate called on FirstViewController (this is still FirstViewController here because the tab bar selection occurred prior to setting the SecondViewController to the tabBarControllerDelegate)

First Tab Selected:
Who's my tab bar controller delegate = <SecondViewController: 0x7fa33ac0a540>
Delegate called on SecondViewController

Second Tab Selected:
Who's my tab bar controller delegate = <SecondViewController: 0x7fa33ac0a540>
Delegate called on SecondViewController

...
 and it continues on that the SecondViewController will remain the delegate

So my recommendation would be to use a different pattern that just maintains one coordinator to handle the TabBarDelegation.

Edit in response to your comment about other recommendations

A rather standard idiom in iOS is loading your data from the server once (usually in viewDidLoad of the respective view controllers then storing it), then having a pull to refresh control which allows users to refresh the data on command: https://medium.com/ios-os-x-development/ios-tips-pull-to-refresh-in-less-than-30-seconds-ef884520f0df If you definitely require the tab bar delegate to do something on each view controller selection, I'd recommend having one central object that is the only tab bar delegate and having it handle what tasks to do based on the view controller passed in through the delegate method tabBarController:didSelectViewController: as one additional example.

这篇关于Objective-C:如何为TabBarController正确设置didSelectViewController方法,以便每次点击VC时都可以刷新VC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆