如何在 `UIPageViewController` 的子视图中引用 `IBOutlet`

Posted

技术标签:

【中文标题】如何在 `UIPageViewController` 的子视图中引用 `IBOutlet`【英文标题】:How reference `IBOutlet`s in subviews of `UIPageViewController` 【发布时间】:2019-01-08 18:36:45 【问题描述】:

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

我有很多观察者更新vc1vc2vc3UIPageViewController 中的“页面”)中的视图。为了保持我的代码干净,我想在UIPageViewController 类中添加所有观察者,而不是在vc1vc2vc3viewDidLoad 中。

但是,我无法引用来自 UIPageViewController 的子视图的 IBOutlets,因为它们为零。有没有人对如何设置UIPageViewController 以我可以访问子视图的IBOutlets 的方式提出建议?

我在其他应用程序更新屏幕上不可见的页面视图时遇到了问题(例如:更新vc3 中的视图而vc1 在屏幕上)。 UIPageViewController 对这种目标来说是个坏主意吗?我应该只制作一个用户可以平移的大视图吗?

// 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)

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

以上是关于如何在 `UIPageViewController` 的子视图中引用 `IBOutlet`的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIPageViewController 中更改页面指示器的背景颜色

如何在 UIPageviewcontroller 中实现静态菜单栏?

如何在视图中移动 UIPageViewController 页面控制器按钮的位置

如何在 UIPageViewcontroller 中添加两个视图控制器

如何在 UIPageViewController 中的两个 ViewController 之间传递数据

iOS - 如何在 UIPageViewController 中设置 UIScrollView 以在重新启用后开始滚动