TabBarController的第二个选项卡未实例化 - > IBOutlets是零

时间:2016-11-27 13:30:36

标签: ios swift uitabbarcontroller iboutlet

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

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

我遇到的是每当我在添加新回合之前没有打开历史记录选项卡时我的程序崩溃,因为我的IBOutlets是零。但每当我先打开标签然后再返回添加新的一轮它就可以了。每回合后我也不必重新打开标签。在我第一次打开它之前看起来没有实例化标签。

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

成功之光: http://i.imgur.com/LqxYBjV.gifv

有没有办法手动执行此操作?

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

2 个答案:

答案 0 :(得分:1)

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

解决方案:

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

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

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

    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了解一种方法。

答案 1 :(得分:0)

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

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

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

希望这有帮助。