Swift / iOS:加载视图控制器后IBOutlet为零 [英] Swift/iOS: IBOutlet nil after loading view controller

查看:276
本文介绍了Swift / iOS:加载视图控制器后IBOutlet为零的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个应用程序(在XCode 8.2.1中),其中一些对象显示在2D板上,当用户点击其中一个对象时,应该将一些信息显示为样式信息框。我的设计是将信息写在一个单独的视图控制器中,我会在需要时显示。

I'm building an app (in XCode 8.2.1) where some objects are displayed on a 2D board, and when the user taps one of these objects some info should be displayed about it as a styled modal info box. My design is to have the info written in a separate view controller, which I would display when needed.

我为第二个视图控制器设计了一个基本存根,并在界面构建器中为它添加了一个标签。然后我将此标签ctrl链接到我的自定义VC类:

I've designed a basic stub for the second view controller and added a single label to it in the interface builder. Then I've ctrl-linked this label to my custom VC class:

class InfoViewController: UIViewController {
    @IBOutlet weak var info: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    func displayInfo() {
        info.attributedText = NSAttributedString(string: "abc")
    }
}

但是,当我测试我的应用并点按该对象时,即使在 viewDidLoad() info 字段 nil 我的自定义VC类的方法。我显示我的VC的方式如下:

However, when I test my app and tap the object, the info field is nil even in the viewDidLoad() method of my custom VC class. The way I'm displaying my VC is as follows:

let infoViewController = InfoViewController()
infoViewController.modalPresentationStyle = .overCurrentContext
self.present(infoViewController, animated: true, completion: nil)
infoViewController.displayInfo()

(注意:最后我只有一个 InfoViewController 的单个实例,但这仅用于测试。我不希望有一个全局实例会有什么不同吗?)

(Note: In the end I will have only one single instance of InfoViewController but this is just for testing. I don't expect having a global instance would make any difference?)

正如我所说,无论是在 viewDidLoad()方法内还是在 displayInfo()方法, info 总是 nil ,这样设置其 attributedString 属性会使应用程序崩溃。认为 present 方法可能是异步调用的,我试过从 displayInfo() > viewDidLoad(),但这没有任何区别。

As I said, be it inside the viewDidLoad() method or in the displayInfo() method, info is always nil, such that setting its attributedString attribute crashes the app. Thinking the present method might be called asynchronously, I've tried calling displayInfo() from inside viewDidLoad(), but that didn't make any difference.

任何人都可以告诉我我忘记了什么会让我的 IBOutlet 正确初始化吗?

Can anyone tell my what I've forgotten that would allow my IBOutlet from being properly initialized properly?

谢谢!

David

推荐答案

问题是对 InfoViewController()的引用,它独立于任何故事板场景实例化视图控制器。您想使用 instantiateViewController

The problem is the reference to InfoViewController(), which instantiates the view controller independent of any storyboard scene. You want to use instantiateViewController:

let infoViewController = storyboard?.instantiateViewController(withIdentifier: "Info") as! InfoViewController
infoViewController.modalPresentationStyle = .overCurrentContext
present(infoViewController, animated: true) {
    infoViewController.displayInfo()
}

几个笔记:


  • 这假定(a)你在故事板中给出了一个故事板id; (b)您已将该场景的基类设置为 InfoViewController

注意,I在 present 的完成处理程序中调用 displayInfo ,因为在场景出现之前你可能不希望调用它这些网点已被连接起来。

Note, I called displayInfo in the completion handler of present because you probably don't want that called until the scene has been presented and the outlets have been hooked up.

或者,你可以更新 InfoViewController 的非出口属性在实例化之后立即使其 viewDidLoad 获取这些属性并更新出口,例如:

Alternatively, you can update non-outlet properties of the InfoViewController immediately after instantiating it and then have its viewDidLoad take those properties and update the outlets, e.g.:

class InfoViewController: UIViewController {
    var info: String!
    @IBOutlet weak var infoLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        infoLabel.attributedText = NSAttributedString(string: info)
    }
}

注意,我将 @IBOutlet 名称更改为 infoLabel 并添加了名为 info String 属性。这往往是惯例,出口带有一些后缀表示控件的类型,模型对象,如 String 属性,没有后缀。 (您只需要确保在IB中的连接检查器中删除旧的插座,这样就不会出现这些属性名称更改的问题。)

Note, I changed the @IBOutlet name to be infoLabel and added the String property called info. That tends to be the convention, that outlets bear some suffix indicating the type of control, and model objects, like the String property, are without the suffix. (You'll just want to make sure you remove that old outlet in the connections inspector in IB so that you don't have problems with these property name changes.)

无论如何,你可以这样做:

Anyway, you can then do:

let infoViewController = storyboard?.instantiateViewController(withIdentifier: "Info") as! InfoViewController
infoViewController.info = "abc"
infoViewController.modalPresentationStyle = .overCurrentContext
present(infoViewController, animated: true, completion: nil)

关键点是在实例化之后不要立即尝试更新场景的出口,但要确保将其推迟到 viewDidLoad 被调用。

The key point is don't try to update outlets of the scene immediately after instantiating it, but make sure that this is deferred until after viewDidLoad was called.

这篇关于Swift / iOS:加载视图控制器后IBOutlet为零的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆