首页 > 解决方案 > 如何在 `UIPageViewController` 的子视图中引用`IBOutlet`

问题描述

我读到如果您通过初始化程序直接实例化一个类(UIViewController),则不会连接 IBOutlets。我的问题是我引用了 nil IBOutlet,导致崩溃。

我有很多观察者会更新vc1vc2vc3(中的“页面” UIPageViewController)中的视图。为了保持我的代码干净,我想在UIPageViewController类中添加所有观察者,而不是在viewDidLoadof vc1, vc2, &vc3中。

但是,我无法引用IBOutlets子视图,UIPageViewController因为它们为零。有没有人有关于如何以UIPageViewController我可以访问子视图的方式进行设置的建议IBOutlets

我在其他应用程序更新屏幕上不可见的页面视图时遇到了麻烦(例如:在屏幕上更新视图vc3vc1UIPageViewController这种目标是个坏主意吗?我应该只制作一个用户可以平移的大视图吗?

// UIPageViewController.swift

var vc1: ViewController1 = {
  let storyboard = UIStoryboard(name: "Main", bundle: nil)
  return (storyboard.instantiateViewController(withIdentifier: "ViewController1") as? ViewController1)!
}()

var vc2: ViewController2 = {
  let storyboard = UIStoryboard(name: "Main", bundle: nil)
  return (storyboard.instantiateViewController(withIdentifier: "ViewController2") as? ViewController2)!
}()

var vc3: ViewController3 = {
  let storyboard = UIStoryboard(name: "Main", bundle: nil)
  return (storyboard.instantiateViewController(withIdentifier: "ViewController3") as? ViewController3)!
}()

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
  if viewController == vc2 {
    return vc1
  } else if viewController == vc3 {
    return vc2
  }
  return nil
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
  if viewController == vc1 {
    return vc2
  } else if viewController == vc2 {
    return vc3
  }
  return nil
}

  func viewDidLayoutSubviews() {
    // Adding observer for ViewController1
    NotificationCenter.default.addObserver(self, selector: #selector(vc1.handleEventDataChange), name: .eventDataChanged, object: nil)
  }

-

// ViewController1.swift

@IBOutlet weak var scoreBoard: UIView!

func viewDidLoad() {
  super.viewDidLoad()
}

func handleEventDataChange() {
  if scoreBoard.alpha != 0 { // <-- Crash here
    // update scoreboard
  }
} 

编辑:

除了 JRTurton 的回答,我还发现我在错误的类中添加了观察者。

NotificationCenter.default.addObserver(self, selector: #selector(vc1.handleEventDataChange), name: .eventDataChanged, object: nil)

应该

NotificationCenter.default.addObserver(vc1, selector: #selector(vc1.handleEventDataChange), name: .eventDataChanged, object: nil)

标签: swiftinstantiationuipageviewcontrolleriboutlet

解决方案


您正在从情节提要加载您的视图控制器,因此插座将被连接(假设它在情节提要中正确连接)。

问题的最可能原因是在视图控制器加载其视图之前调用了这些方法,因此它们还没有机会连接任何东西。

对插座有副作用的外部调用函数可能应该从检查开始isViewLoaded以防止此问题。理想情况下,您应该配置模型对象以传递给您的视图控制器,视图控制器可以立即操作(如果视图已加载)或用于配置viewDidLoad

(另外,视图没有布局子视图不是添加观察者的好地方 - 这可以被称为很多


推荐阅读