Ios 为什么可以';我不能在UIPageViewController中设置视图控制器吗?

Ios 为什么可以';我不能在UIPageViewController中设置视图控制器吗?,ios,arrays,swift,uiviewcontroller,uipageviewcontroller,Ios,Arrays,Swift,Uiviewcontroller,Uipageviewcontroller,我试图用从API中提取的5个事件填充页面视图控制器。其想法是,用户可以翻阅前5名的最新事件,然后单击它们以查看有关该事件的更多详细信息。我遇到的问题是,一旦我获得事件,我想为页面视图控制器重新加载视图控制器,但当我尝试设置视图控制器时,我得到一个错误:致命错误:在展开可选值时意外发现nil。我为我的事件数组设置了一个属性观察器,这样一旦设置了属性观察器,我就可以重新加载视图控制器。我的班级是这样的: class EventPageViewController:UIPageViewControll

我试图用从API中提取的5个事件填充页面视图控制器。其想法是,用户可以翻阅前5名的最新事件,然后单击它们以查看有关该事件的更多详细信息。我遇到的问题是,一旦我获得事件,我想为页面视图控制器重新加载视图控制器,但当我尝试设置视图控制器时,我得到一个错误:
致命错误:在展开可选值时意外发现nil
。我为我的事件数组设置了一个属性观察器,这样一旦设置了属性观察器,我就可以重新加载视图控制器。我的班级是这样的:

class EventPageViewController:UIPageViewController{
var eventViewControllers=[EventViewController]()
变量事件:[事件]=[]{
迪塞特{
self.reloadViewControllers()
}
}
func重载视图控制器(){
self.dataSource=nil
self.dataSource=self
//获得前5项赛事
让topFiveEvents=Array(events.prefix(5))
打印(self.events.count)
self.eventViewControllers.removeAll()
打印(EventViewController.count)
//设置视图控制器
对于topFiveEvents中的事件{
如果let controller=self.storyboard?.instanceeviewcontroller(带有标识符:“event”)作为?EventViewController{
打印(事件标题)
//仅仅这一行就足以使应用程序崩溃
controller.eventTitle.text=event.title
self.eventViewController.append(控制器)
}
}
如果self.eventViewControllers.count!=0{
let first=[self.eventViewControllers[0]]
self.setViewController(第一个,方向:。正向,动画:false,完成:nil)
}
}
重写func viewDidLoad(){
super.viewDidLoad()
让timeMin=GTLRDateTime(日期:date()).rfc3339String
设params=[“maxResults”:“250”,
“singleEvents”:“true”,
“timeMin”:timeMin]
NetworkManager.events(forPark:.all,带参数:params,query:nil){(events,error)在
如果错误==nil{
DispatchQueue.main.async{
self.events=事件
}
}
}
}
重写func viewdilayoutsubviews(){
对于self.view.subView中的子视图{
如果子视图是UIScrollView{
subView.frame=self.view.bounds
}否则,如果子视图是UIPageControl{
将pageControl=子视图设为!UIPageControl
pageControl.currentPageIndicatorTintColor=UIColor(红色:0.00,绿色:0.15,蓝色:0.29,alpha:1.0)
pageControl.pageIndicatorTintColor=UIColor(红色:0.00,绿色:0.15,蓝色:0.29,alpha:0.30)
self.view.bringSubview(toFront:subView)
}
}
super.viewDidLayoutSubviews()
}
}

如果我没有在视图控制器中设置任何内容,那么我会让页面视图控制器显示带有静态信息的视图控制器。我不确定我做错了什么。

在我看来,您的页面视图控制器正试图直接操纵其子视图控制器的视图。不要那样做

这一行:

controller.eventTitle.text = event.title
可能是原因,假设
eventTitle
是一个出口

不要这样做,而是将字符串属性添加到子视图控制器:

public var eventTitleString: String
然后设置为:

controller.eventTitleString = event.title
在子视图控制器中,添加代码以将该值复制到字段中:

func viewWillAppear(_: animated: Bool) {
  super.viewWillAppear(animated)
  eventTitle.text = eventTitleString
}

@Saturn建议调用
controller.loadViewIfNeeded()
,这可能会修复您的崩溃,但这是一种不好的做法。您应该将视图控制器的视图视为私有视图,并且永远不要尝试从外部操纵它们。而是添加一个直接更新视图控制器视图的公共属性或函数。

在我看来,您的页面视图控制器正试图直接操作其子视图控制器的视图。不要那样做

这一行:

controller.eventTitle.text = event.title
可能是原因,假设
eventTitle
是一个出口

不要这样做,而是将字符串属性添加到子视图控制器:

public var eventTitleString: String
然后设置为:

controller.eventTitleString = event.title
在子视图控制器中,添加代码以将该值复制到字段中:

func viewWillAppear(_: animated: Bool) {
  super.viewWillAppear(animated)
  eventTitle.text = eventTitleString
}

@Saturn建议调用
controller.loadViewIfNeeded()
,这可能会修复您的崩溃,但这是一种不好的做法。您应该将视图控制器的视图视为私有视图,并且永远不要尝试从外部操纵它们。相反,添加一个直接更新视图控制器视图的公共属性或函数。

谢谢,我不知道操作子视图控制器视图是一种不好的做法,但您的解决方案起了作用。“封装”原则是面向对象设计的一个基本原则。在设计对象时,考虑为对象提供给其他对象的服务建立公共“契约”。该部分应外露,并可供其他对象使用。其他任何东西都应该是私有的,并且在对象本身之外是禁止的。这样,对象对其他对象的实现细节不敏感。只要它们的公共界面保持稳定,内部可以以大小的方式改变,一切都可以正常工作。如果您创建一个视图控制器来收集用户的输入并将其报告给另一个视图控制器,那么该视图控制器应该可以自由地切换到使用不同类型的控件,或者以用户想要的任何方式向用户显示信息。它所需要做的就是拥有相同的属性和方法。当另一个对象直接操纵视图控制器的视图时,您将视图控制器锁定为始终以相同的方式实现其视图。谢谢,我不知道操纵子视图控制器视图是一种不好的做法,但您的解决方案起了作用。“封装”原则是面向对象设计的基本原则。在设计对象时,考虑为对象提供给其他对象的服务建立公共“契约”。那部分应该是b