xcode Swift/iOS:加载视图控制器后 IBOutlet 为零
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41453042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift/iOS: IBOutlet nil after loading view controller
提问by David
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.
我正在构建一个应用程序(在 XCode 8.2.1 中),其中一些对象显示在 2D 板上,并且当用户点击这些对象之一时,应将有关它的一些信息显示为样式化的模态信息框。我的设计是将信息写在一个单独的视图控制器中,我会在需要时显示。
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:
我为第二个视图控制器设计了一个基本存根,并在界面构建器中为其添加了一个标签。然后我将这个标签链接到我的自定义 VC 类:
class InfoViewController: UIViewController {
@IBOutlet weak var info: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func displayInfo() {
info.attributedText = NSAttributedString(string: "abc")
}
}
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:
但是,当我测试我的应用程序并点击对象时,该info
字段nil
甚至在viewDidLoad()
我的自定义 VC 类的方法中。我显示我的 VC 的方式如下:
let infoViewController = InfoViewController()
infoViewController.modalPresentationStyle = .overCurrentContext
self.present(infoViewController, animated: true, completion: nil)
infoViewController.displayInfo()
(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?)
(注意:最后我将只有一个实例,InfoViewController
但这仅用于测试。我不希望拥有一个全局实例会有什么不同?)
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.
正如我所说,无论是在viewDidLoad()
方法内部还是在displayInfo()
方法中,info
总是nil
,这样设置其attributedString
属性会使应用程序崩溃。认为该present
方法可能会被异步调用,我尝试displayInfo()
从 inside调用viewDidLoad()
,但这没有任何区别。
Can anyone tell my what I've forgotten that would allow my IBOutlet
from being properly initialized properly?
谁能告诉我我忘记了什么可以让我IBOutlet
正确初始化?
Thanks!
谢谢!
David
大卫
回答by Rob
The problem is the reference to InfoViewController()
, which instantiates the view controller independent of any storyboard scene. You want to use instantiateViewController
:
问题是对 的引用InfoViewController()
,它实例化独立于任何故事板场景的视图控制器。你想使用instantiateViewController
:
let infoViewController = storyboard?.instantiateViewController(withIdentifier: "Info") as! InfoViewController
infoViewController.modalPresentationStyle = .overCurrentContext
present(infoViewController, animated: true) {
infoViewController.displayInfo()
}
A couple of notes:
一些注意事项:
This assumes that (a) you've given the scene in the storyboard a "storyboard id"; (b) you've set the base class for that scene to
InfoViewController
.Note, I called
displayInfo
in the completion handler ofpresent
because you probably don't want that called until the scene has been presented and the outlets have been hooked up.
这假设 (a) 您已为情节提要中的场景指定了“情节提要 ID”;(b) 您已将该场景的基类设置为
InfoViewController
.请注意,我调用
displayInfo
了 的完成处理程序,present
因为您可能不希望在呈现场景并且连接插座之前调用它。
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.:
或者,您可以InfoViewController
在实例化之后立即更新它的非出口属性,然后让它viewDidLoad
获取这些属性并更新出口,例如:
class InfoViewController: UIViewController {
var info: String!
@IBOutlet weak var infoLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
infoLabel.attributedText = NSAttributedString(string: info)
}
}
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.)
请注意,我将@IBOutlet
名称更改为infoLabel
并添加了String
名为info
. 这往往是约定俗成的,即出口带有一些表示控件类型的后缀,而模型对象(如String
属性)则没有后缀。(您只需要确保在 IB 的连接检查器中删除旧插座,这样您就不会遇到这些属性名称更改的问题。)
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)
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.
关键是不要尝试在实例化后立即更新场景的出口,但要确保将其推迟到viewDidLoad
被调用之后。
回答by iOS Lifee
I Replaced
我替换了
let vc = CCDetailViewController()
With
和
let vc = self.storyboard?.instantiateViewController(withIdentifier: "CCDetailViewController")
Finally
最后
self.present(vc!, animated: true, completion: nil)
Now It Works...
现在它有效...
回答by Suresh Vutukuru
In my case, I had created new view controller for the same class. Which had ended up with two view controllers in storyboard, but referring to the same class. After deleting old view controller, everything worked fine.
就我而言,我为同一个类创建了新的视图控制器。最终在故事板中有两个视图控制器,但指的是同一个类。删除旧的视图控制器后,一切正常。
Hope it helps to someone.
希望它对某人有所帮助。