TabBarController 的第二个选项卡未实例化 -> IBOutlets 为 nil

TabBarController's second tab doesn't get instantiated -> IBOutlets are nil

我正在创建一个简单的应用程序,它有一个选项卡栏控制器,其中摘要是一个选项卡,历史记录是另一个选项卡。在摘要选项卡中,有一个用于添加新回合的按钮。每当添加此回合时,它也必须转到历史选项卡。

我正在尝试通过 tabBarController 发送数据。

我遇到的情况是,每当我在添加新一轮之前不打开历史选项卡时,我的程序就会崩溃,因为我的 IBOutlets 为零。但是每当我先打开选项卡然后返回添加新回合时,它都可以正常工作。我也不必在每一轮之后重新打开选项卡。在我第一次打开它之前,该选项卡似乎没有被实例化。

失败的Gif(错误是图表View为零): http://i.imgur.com/VPa0RmK.gifv

成功动图: http://i.imgur.com/LqxYBjV.gifv

有什么方法可以手动执行此操作吗?

我是 iOS 编程的新手,所以这就是我认为的问题所在。如果发生其他导致我的代码崩溃的事情,我想知道!

它应该是这样工作的。每个选项卡仅在必须显示时才创建。这与 TableViews 和 CollectionViews 的想法相同。

为您解决此问题的简单方法是覆盖 HistoryViewController 的 viewWillAppear(或 viewDidAppear)方法并从那里刷新 UI。

这样,您永远不会假设“历史记录”选项卡存在于“摘要”选项卡中,“历史记录”会自行刷新其 UI。

希望对您有所帮助。

你是对的。问题是第二个选项卡的插座在您访问该选项卡之前不会设置。

解决方案:

  1. 您可以将数据写入第二个 viewController 的 属性,然后将该数据移动到覆盖 viewWillAppear 的出口中。

  2. 另一种可能性是在写入之前检查插座是否为 nil。如果是,请在第二个 viewController 上调用 loadView 告诉它设置它的出口,然后你就可以给它们写信了。请注意,如果您手动调用 loadView,则方法 viewDidLoad 将不会 运行,因此如果您在那里进行任何其他设置,您还需要从 loadView.

  3. 也许比手动调用loadView更简单的是通过访问view属性来触发secondViewController的viewDidLoad。这可以很简单:

    if let svc = self.tabBarController?.viewControllers?[1] as? SecondViewController {
        // check if outlet is nil
        if svc.myLabel == nil {
            // trigger viewDidLoad to set up the outlets
            _ = svc.view
        }
        svc.myLabel = "Success!"
    }
    
  4. 也就是说,直接访问另一个 viewController 的视图(即插座)是糟糕的设计,并且违反了 MVC(模型-视图-控制器)范例。你真的应该把你的数据放在一个所有选项卡都可以访问的地方,然后在选择选项卡时让每个 viewController 在 viewWillAppear 中更新自己。请参阅此答案:Sharing data in a TabBarController 了解执行此操作的一种方法。