我今天试图从Obj-C开始到Swift,我正在阅读文档。我试图在Swift中创建一个简单的IBOutlet,它不断给我这些错误。
View Controller has no initialiser
必需的init(编码器aDecoder:NSCoder){ fatalError(“init(编码器:)尚未实现”)}
IBOutletproperty has non-optional type 'UILabel'
并且不断弹出这段代码:
@IBOutlet var outputLabel : UILabel
但是当我添加一个!标记,它运行没有错误,如此
@IBOutlet var outputLabel : UILabel!
IBActions也是如此......
答案 0 :(得分:10)
首先要了解,实际上是!
和?
?
:如果以后该值可能为零,那么您可以对此进行测试。!
:如果将来真的不应该为零,但最初需要为零。<强> @IBOutlet:强>
当您在Swift中声明一个插座时,编译器会自动将类型转换为弱隐式解包的可选,并为其指定初始值nil
。
实际上,编译器将@IBOutlet var name:
Type替换为@IBOutlet weak var name: Type! = nil
。
Xcode会更改它并强制限制声明@IBOutlet
非选项类型变量,因此@IBOutlet
的两种声明都是有效的直到日期。
@IBOutlet var outputLabel : UILabel!
@IBOutlet var priceLabel : UILabel?
但是,如果您控制在测试版4中拖动标签的插座,则会发生这种情况:
@IBOutlet var priceLabel : UILabel! = nil
答案 1 :(得分:6)
接口构建器数据在视图控制器启动后加载,因此在初始化后出口不能具有值。使用隐式展开的可选属性(在这种情况下为outlet),您承诺在启动对象后属性可能为nil,但稍后将分配它们的值(在加载nib或storyboard之后)。
答案 2 :(得分:5)
这是正确的。在Swift中,X类型的变量不能为nil,这意味着它必须被初始化。这意味着您必须使用init
方法或内联初始化来初始化。
通常,视图控制器将声明可选类型的变量 - 例如,
@IBOutlet var outputLabel : UILabel!
这意味着您无需初始化outputLabel
,默认情况下,它的值为nil
。这是IBOutlet
变量的一般模式,因为变量是在init
方法之外设置的。
如果不使变量可选,则必须对其进行初始化。如果不初始化内联,则必须提供init
方法 - 因此会出现错误。
答案 3 :(得分:1)
由于Stack允许Q和A风格的问题,我还会把它变成更容易的单词。只需将!
放在网点和网点上即可。非常感谢你的帮助。
答案 4 :(得分:0)
错误
'required' initialized 'init(coder:)' must be provided by subclass of 'UIViewController'
当我添加时,突然开始了
var start : NSDate
到UIViewController以前工作的子类,否则全部在IB中生成。 改为
var start : NSDate?
固定。这是一个令人惊讶的错误(呵呵?init?编码器?),对于一个简单的编辑,有人启动应用程序可能会在他们遇到编码器或创建他们自己的init方法之前做很久,这可能有助于明确显示初始化需求不仅限于IBOutlets。上面的答案描述了根本原因。
答案 5 :(得分:0)
从界面构建器文件初始化视图或视图控制器时,它们的插座尚未连接。它们只会在初始化后连接,因此它们必须是可选的。但是,如果在初始化之后调用类中的任何其他代码,则保证连接这些插座。这就是为什么IBOutlets总是被声明为隐式解包的选项。
答案 6 :(得分:0)
虽然XCode似乎在祝福这种行为,但它仍然是不安全的,并且您始终牢记您可能希望做出一些可选。
虽然IB将为您初始化这些,但这并不能保证它们以后不会成为零。例如,如果您需要删除IBOutlet作为子视图,或者有条件地设置NSLayoutConstraint.isActive = false(令人讨厌的隐身零)。