Ios 如何从PageViewController访问ViewController组件

Ios 如何从PageViewController访问ViewController组件,ios,swift,Ios,Swift,我有两个简单的视图,如下所示 第一个是PageView第二个是简单的viewController,上面有一个图像视图 viewController代码如下所示 class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.white imgView.image

我有两个简单的视图,如下所示

第一个是PageView第二个是简单的viewController,上面有一个图像视图

viewController代码如下所示

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white
        imgView.image = UIImage(named: "dog0")
    }
}
当我作为初始视图控制器运行此视图控制器时。它很好用。它正确地显示了图像

但是当我使用下面的代码从页面视图控制器执行同样的操作时

class PageViewController: UIPageViewController, UIPageViewControllerDataSource {

    let imageNames = ["dog0","dog1","dog2"]
    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = self
        let eachView = ViewController()
        eachView.imageName = imageNames.first
        let viewControllers = [eachView]
        setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        return nil
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        return nil
    }


}

我得到以下错误

fatal error: unexpectedly found nil while unwrapping an Optional value
在线

imgView.image = UIImage(named: imageName!)

问题是什么?如何解决?

问题是这一行:

let eachView = ViewController()
这将“凭空”创建一个ViewController实例,没有任何关联的主视图。因此,当视图加载时,它是空的。因此,视图中没有图像视图,
imgView
nil
。因此,当您参考
imgView
时,就好像它不是
nil
(试图设置它的
图像
),您会崩溃

正确的步骤是实例化在故事板中设计的ViewController。ViewController实例在其
视图中有一个图像视图,这是因为您设计了它(您将其放在那里),并且它有一个
imgView
出口,正如您已经知道的,这也是因为您设计了它(您将其放在那里)

要获取该ViewController实例,请获取对情节提要的引用(可能为
self.storyboard
)并调用。当然,您必须在情节提要中为该ViewController实例指定一个标识符

然后您需要像这样重写ViewController:

class ViewController: UIViewController {
    var imageName : String? {
        didSet {
            imgView?.image = UIImage(named: imageName!)
        }
    }
    @IBOutlet weak var imgView: UIImageView? // note the question mark

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white
        imgView?.image = UIImage(named: imageName!) // note the repeat
    }
}

原因是您现在有一个计时问题:您正在加载视图之前设置
imageName
,因此
imgView
仍然没有连接到其出口。通过将关键行移动到
viewdiload
,您可以确保我们在实际拥有视图和插座后执行此操作。

问题在于这行:

let eachView = ViewController()
这将“凭空”创建一个ViewController实例,没有任何关联的主视图。因此,当视图加载时,它是空的。因此,视图中没有图像视图,
imgView
nil
。因此,当您参考
imgView
时,就好像它不是
nil
(试图设置它的
图像
),您会崩溃

正确的步骤是实例化在故事板中设计的ViewController。ViewController实例在其
视图中有一个图像视图,这是因为您设计了它(您将其放在那里),并且它有一个
imgView
出口,正如您已经知道的,这也是因为您设计了它(您将其放在那里)

要获取该ViewController实例,请获取对情节提要的引用(可能为
self.storyboard
)并调用。当然,您必须在情节提要中为该ViewController实例指定一个标识符

然后您需要像这样重写ViewController:

class ViewController: UIViewController {
    var imageName : String? {
        didSet {
            imgView?.image = UIImage(named: imageName!)
        }
    }
    @IBOutlet weak var imgView: UIImageView? // note the question mark

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.white
        imgView?.image = UIImage(named: imageName!) // note the repeat
    }
}

原因是您现在有一个计时问题:您正在加载视图之前设置
imageName
,因此
imgView
仍然没有连接到其出口。通过将关键行移动到
viewDidLoad
,您可以确保我们在实际拥有一个视图和一个插座后执行此操作。

如何解决此问题?@LynAs我想我现在已经提供了充分的解释!如果您还有其他问题,请告诉我。我正在以这种方式实例化视图控制器
让eachView=self.storyboard?。实例化eviewController(带有标识符:“imageScroller”)为!ViewController
仍然收到相同的错误。你能告诉我为什么吗?我也尝试了
让eachView=UIStoryboard(名称:“Main”,bundle:nil)。实例化eviewController(带有标识符:“imageScroller”)为!ViewController
ok我最终使用UserDefaults传递图像名称。这看起来不是正确的方法,但目前对我有效。我如何解决这个问题?@LynAs我想我现在已经提供了充分的解释!如果您还有其他问题,请告诉我。我正在以这种方式实例化视图控制器
让eachView=self.storyboard?。实例化eviewController(带有标识符:“imageScroller”)为!ViewController
仍然收到相同的错误。你能告诉我为什么吗?我也尝试了
让eachView=UIStoryboard(名称:“Main”,bundle:nil)。实例化eviewController(带有标识符:“imageScroller”)为!ViewController
ok我最终使用UserDefaults传递图像名称。这看起来不是正确的方法,但现在对我来说很有效