【问题标题】:Accessing elements from another view controller comes up nil从另一个视图控制器访问元素出现 nil
【发布时间】:2017-05-18 02:51:27
【问题描述】:

我有一个使用来自 GitHub 的 presentr 制作的警报视图。我使用了一个简单的view controller,它将覆盖在当前视图控制器上。现在我有来自first view controllerUIImageUIlabel 等元素需要alert view controller 访问。但是当我单击alert view controller 中的取消按钮以从firstviewcontroller 的uilabel 访问uiimagetext 时。这是代码。你能告诉我如何解决这个问题。我无法对数据进行 segue,因为我正在呈现视图控制器,而我试图访问的数据无论如何都过于 segue。我不断收到此错误“致命错误:在展开可选值时意外发现 nil”超时我单击alertviewcontroller 中的保存按钮。

class firstviewcontroller: UIViewController{
    var photos2: [ImageSource]?
    @IBOutlet weak var Label: UIlabel!
    @IBOutlet weak var Image: UIImage!
}

class alertviewcontroller: UIViewController{
    @IBAction func Save(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        let storyboard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
        let firstViewController: firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "firstviewcontroller") as! firstviewcontroller

        if let image = firstViewController.Image { 
            imageview.image = image
        }
        if let label = firstViewController.Label {
            label.text = Label.text
        }
    }
}

【问题讨论】:

  • 你是如何实例化 alertViewController 的?如果您使用情节提要执行此操作,则将数据传递给子 VC 的标准方法是通过 segue。
  • 顺便说一句,按照惯例,所有类都以大写字母开头,所有实例都以小写字母开头。您的代码非常混乱,因为类和实例都是firstviewcontroller。该类应称为Firstviewcontroller 以避免这种混淆。

标签: ios iphone swift xcode swift3


【解决方案1】:

您犯的最大错误是您正在创建firstviewcontroller 的新实例,而不是仅访问当前实例。

class alertviewcontroller: UIViewController{
    @IBAction func Save(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        let storyboard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
        let firstViewController: firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "firstviewcontroller") as! firstviewcontroller // This is the mistake

        if let image = firstViewController.Image { 
            imageview.image = image
        }
        if let label = firstViewController.Label {
            label.text = Label.text
        }
    }
}

您应该做的是访问presentingViewController,因为您使用present 函数提供了alertviewcontroller

代码如下所示

class alertviewcontroller: UIViewController{
    @IBAction func Save(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        let storyboard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)

        // NOTE: only do implicit unwrapping `as!` if you're sure that the value you're unwrapping is not `nil` or it is of the correct `data type` cause it might cause your app to crash
        let firstViewController: firstviewcontroller = self.presentingViewController as! firstviewcontroller

        if let image = firstViewController.Image { 
            imageview.image = image
        }
        if let label = firstViewController.Label {
            label.text = Label.text
        }
    }
}

提示:请查看 Swift 编码指南,因为您的 methodsvariablesclasses 的命名存在一些小错误。

【讨论】:

    【解决方案2】:

    可能我错了,但是在查看了您的代码后,我发现了这个混乱的陈述

    let firstViewController: firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "firstviewcontroller") as! firstviewcontroller
    

    在此语句中,您正在创建 firstviewcontroller 的新实例,而不是访问已创建的 firstviewcontroller 实例。

    接下来,你说

    我使用了一个简单的视图控制器,它将覆盖当前 视图控制器

    所以我假设您没有在当前 viewController 上呈现或推送 alertviewcontroller,在这种行为上我建议您使用以下解决方案

    1. alertviewcontroller中使用该方法获取topViewController的实例

      class func topViewController(base: UIViewController? = (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
          if let nav = base as? UINavigationController {
              return topViewController(base: nav.visibleViewController)
          }
          if let tab = base as? UITabBarController {
              if let selected = tab.selectedViewController {
                  return topViewController(base: selected)
              }
          }
          if let presented = base?.presentedViewController {
              return topViewController(base: presented)
          }
          return base
      }
      

    然后您可以将您的数据从alertviewcontroller 传输到topViewController。

    1. 下一个解决方案是您可以使用委托将值从 alertviewcontroller 传递到 firstviewcontroller

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多