为什么 UIKit 不喜欢 Swift 3 个可选项?
Why UIKit doesn't like Swift 3 optionals?
以下 Swift 3 代码崩溃。通过删除显式可选类型或强制展开 view
可以轻松解决崩溃。谁能解释一下为什么这段代码会崩溃?
let view: UIView? = UIView() // note the explicit *optional* type
_ = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 44.0)
注意:它不会用 Swift 2.3 或更低版本
编译
NSLayoutConstraint(item:, attribute:, relatedBy:, toItem:, attribute:, multiplier:, constant:)
有一个 item
参数类型为 Any
:
public convenience init(item view1: Any, attribute attr1: NSLayoutAttribute, relatedBy relation: NSLayoutRelation, toItem view2: Any?, attribute attr2: NSLayoutAttribute, multiplier: CGFloat, constant c: CGFloat)
但是从崩溃中你可以了解到参数实际上只能接受 UIView
或 UILayoutGuide
:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSLayoutConstraint for Optional(UIView: 0x7fa0fbd06650; frame = (0 0; 0 0); layer = CALayer: 0x60800003bb60): Constraint items must each be an instance of UIView, or UILayoutGuide.'
编译器无法在编译期间检查 item
的类型。它被定义为接受任何东西。但是在我们无法访问的实现细节中,该方法仅接受非可选的 UIView
s 或 UILayoutGuide
s.
所以只需添加一个guard
语句:
let view: UIView? = UIView()
guard let view = view else { // Proceed only if unwrapped
fatalError()
}
let _ = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 44.0)
崩溃的原因是UIView
和UIView?
是完全不同的类型。 UIView
是 Objective-C class,而 UIView?
是 Swift 枚举 其中可以包含 UIView
。相反,在 Objective-C 中 nullable
只是对编译器的提示。
以下 Swift 3 代码崩溃。通过删除显式可选类型或强制展开 view
可以轻松解决崩溃。谁能解释一下为什么这段代码会崩溃?
let view: UIView? = UIView() // note the explicit *optional* type
_ = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 44.0)
注意:它不会用 Swift 2.3 或更低版本
编译NSLayoutConstraint(item:, attribute:, relatedBy:, toItem:, attribute:, multiplier:, constant:)
有一个 item
参数类型为 Any
:
public convenience init(item view1: Any, attribute attr1: NSLayoutAttribute, relatedBy relation: NSLayoutRelation, toItem view2: Any?, attribute attr2: NSLayoutAttribute, multiplier: CGFloat, constant c: CGFloat)
但是从崩溃中你可以了解到参数实际上只能接受 UIView
或 UILayoutGuide
:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSLayoutConstraint for Optional(UIView: 0x7fa0fbd06650; frame = (0 0; 0 0); layer = CALayer: 0x60800003bb60): Constraint items must each be an instance of UIView, or UILayoutGuide.'
编译器无法在编译期间检查 item
的类型。它被定义为接受任何东西。但是在我们无法访问的实现细节中,该方法仅接受非可选的 UIView
s 或 UILayoutGuide
s.
所以只需添加一个guard
语句:
let view: UIView? = UIView()
guard let view = view else { // Proceed only if unwrapped
fatalError()
}
let _ = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 44.0)
崩溃的原因是UIView
和UIView?
是完全不同的类型。 UIView
是 Objective-C class,而 UIView?
是 Swift 枚举 其中可以包含 UIView
。相反,在 Objective-C 中 nullable
只是对编译器的提示。