【问题标题】:didSelectViewController does not get called on certain occasionsdidSelectViewController 在某些情况下不会被调用
【发布时间】:2013-07-08 19:20:39
【问题描述】:

我有很多人已经报告过的问题,didSelectViewController 没有被调用,但在我的情况下,它有时会被调用。我有三个选项卡和三个视图控制器。每次用户按下第二个或第三个选项卡时,我都需要执行一些代码。在我的 SecondViewController 和 ThirdViewController 中,我有:

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

现在 SecondViewController 一切正常,每次按下第二个选项卡时都会调用 didSelectViewController。同样在 ThirdViewController didSelectViewControllergets 中,每次按下第三个选项卡时都会调用,但仅在同时未按下第二个栏时调用。因此,当我在 FirstViewController 和 ThirdViewController 之间来回切换时,一切正常。但是当我进入像 first->second->third 这样的模式时,didSelectViewController 不会在 ThirdViewController 中被调用。同样,当我第一次在 ThirdViewController 中调用但不是第二次时,我像 first->third->second->third didSelectViewController 一样。有什么想法吗?

【问题讨论】:

  • 在您删除之前我碰巧注意到您对我的答案的评论,并且我已经编辑了我的答案,并提供了一些提示如何将示例代码集成到您的项目中。

标签: ios uitabbarcontroller


【解决方案1】:

很难理解您到底在做什么,但据我了解,您通过在SecondViewControllerThirdViewController 之间来回更改UITabBarController 的代表来响应选项卡切换。

如果这是真的,我建议不要这样做。相反,我建议您尝试以下方法:

  • 分配一个永不改变的委托。首先,您可以使用您的应用程序委托,但如果您有一个专门的小班可能会更好。我敢肯定,现在您有一个不变的代表,它将 100% 获得对 tabBarController: didSelectViewController: 的所有调用。
  • 作为委托的对象必须同时引用SecondViewControllerThirdViewController 实例。如果您正在使用 Interface Builder 设计您的 UI,您可以通过将两个 IBOutlets 添加到委托类并将适当的实例连接到插座来做到这一点。
  • 现在,当代理收到tabBarController: didSelectViewController: 时,它可以简单地将通知转发到SecondViewControllerThirdViewController,具体取决于选择了哪个选项卡。

一个基本的代码示例:

// TabBarControllerDelegate.h file
@interface TabBarControllerDelegate : NSObject <UITabBarControllerDelegate>
{
}

@property(nonatomic, retain) IBOutlet SecondViewController* secondViewController;
@property(nonatomic, retain) IBOutlet ThirdViewController* thirdViewController;


// TabBarControllerDelegate.m file
- (void) tabBarController:(UITabBarController*)tabBarController didSelectViewController:(UIViewController*)viewController
{
    if (viewController == self.secondViewController)
      [self.secondViewController doSomething];
    else if (viewController == self.thirdViewController)
      [self.thirdViewController doSomethingElse];
}

编辑

关于如何将上面的示例代码集成到您的项目中的一些提示:

  • TabBarControllerDelegate 的实例添加到还包含TabBarController 的.xib 文件中
  • TabBarController'的delegate出口连接到TabBarControllerDelegate实例
  • TabBarControllerDelegatesecondViewController 出口连接到SecondViewController 实例
  • TabBarControllerDelegatethirdViewController 出口连接到ThirdViewController 实例
  • 将方法- (void) doSomething添加到SecondViewController
  • 将方法- (void) doSomethingElse添加到ThirdViewController
  • 确保SecondViewControllerThirdViewController 中没有留下任何代码更改TabBarController 委托!

一旦一切准备就绪并且一切正常,您可能需要清理一下:

  • 将通知方法 doSomethingdoSomethingElse 的名称更改为更合理的名称
  • 如果您关注了 cmets 中的讨论,也许您也想摆脱 secondViewControllerthirdViewController 出口

【讨论】:

  • +1 大部分同意,但我不明白为什么选项卡控制器委托需要每个视图控制器的插座。选项卡控制器不会选择无效的视图控制器,它会告诉您它选择了哪个视图控制器,所以只需向控制器发送一条消息,它告诉您(在首先检查以确保控制器实现方法,当然)。
  • @Caleb 你说得有道理。如果代表向两个 VC 发送完全相同的消息,则代表将不需要出口。在我的代码示例中,我需要区分两个控制器,因为我发送了两个不同的消息doSomethingdoSomethingElse。 @flouwer:如果您希望我编辑我的答案,请告诉我。
  • 我明白了。是否存在您希望选项卡控制器委托而不是视图控制器决定在选择给定控制器时做什么的真实情况?似乎该决定属于每个视图控制器。
  • @Caleb 这主要是理论上的,你当然是正确的,VC 有责任决定做什么。拥有 outlet 的主要(或者可能是唯一)优点是您可以使用具体类型发送通知消息,这将让编译器检查您是否做了正确的事情。如果您没有具体类型,则必须使用 id 类型发送消息以防止编译器警告。
  • @herzbube 非常好的答案,它几乎可以工作。我遇到的唯一问题是将 self.secondViewController 连接到实际的 SecondViewController。现在 self.secondViewController 为 nil,因此 if 比较不正确,即使我按下显示 SecondViewController 的第二个选项卡。
【解决方案2】:

我也遇到过这个问题,受够了。我决定继承UITabBarController 并覆盖以下方法。我这样做的原因是由于某种原因在应用程序启动时setSelectedViewController: 没有被调用。

- (void)setSelectedIndex:(NSUInteger)selectedIndex
{
    [super setSelectedIndex:selectedIndex];
    // my code
}

- (void)setSelectedViewController:(UIViewController *)selectedViewController
{
    [super setSelectedViewController:selectedViewController];
    // my code
}

【讨论】:

    【解决方案3】:

    我刚刚在情节提要上浏览了this tutorial,我想到了使用UITabBarControllerDelegate 的替代方法。如果您想坚持UITabBarControllerDelegate,请随意忽略此答案。

    首先,创建UITabBarController 的子类,我们称之为MyTabBarController。在故事板编辑器中,您需要更改标签栏控制器的“类”属性,以便故事板选择您的新类。

    将此代码添加到MyTabBarController.m

    - (void) prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
    {
      if ([segue.identifier isEqualToString:@"SecondVC"])
      {
        SecondViewController* secondViewController = (SecondViewController*)segue.destinationViewController;
        [secondViewController doSomething];
      }
      else if ([segue.identifier isEqualToString:@"ThirdVC"])
      {
        ThirdViewController* thirdViewController = (ThirdViewController*)segue.destinationViewController;
        [thirdViewController doSomethingElse];
      }
    }
    

    在故事板编辑器中,您现在可以选择连接到SecondViewControllerThirdViewController 的两个segue,并将segue 标识符分别更改为“SecondVC”和“ThirdVC”。

    如果我没记错的话,这就是你需要做的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 1970-01-01
      • 2013-12-05
      • 2021-06-05
      相关资源
      最近更新 更多