Swift:设置协议的可选属性
如何设置协议的可选属性?例如,UITRAITS有许多可选的读/写属性。当我尝试以下操作时,我得到一个编译错误(无法在“TextInputRaits”中分配给“keyboardType”): 通常,在访问协议的可选属性时,您会添加问号,但在指定值时,这不起作用(错误:无法指定此表达式的结果): 协议如下所示:Swift:设置协议的可选属性,swift,Swift,如何设置协议的可选属性?例如,UITRAITS有许多可选的读/写属性。当我尝试以下操作时,我得到一个编译错误(无法在“TextInputRaits”中分配给“keyboardType”): 通常,在访问协议的可选属性时,您会添加问号,但在指定值时,这不起作用(错误:无法指定此表达式的结果): 协议如下所示: protocol UITextInputTraits : NSObjectProtocol { optional var keyboardType: UIKeyboardType { g
protocol UITextInputTraits : NSObjectProtocol {
optional var keyboardType: UIKeyboardType { get set }
}
这在斯威夫特是不可能的。引用自:
当访问或调用可选属性要求和返回值的可选方法要求时,将始终返回相应类型的可选值,以反映可选要求可能尚未实现的事实
因此,轻松获得可选值也就不足为奇了。但是,设置属性需要保证实现
一种解决方法是创建另一个协议,该协议符合第一个协议,但将该可选属性声明为强制属性。然后尝试将对象强制转换为新协议,如果转换成功,我们可以直接访问该属性
protocol UITextInputTraitsWithKeyboardType : UITextInputTraits {
// redeclare the keyboardType property of the parent protocol, but this time as mandatory
var keyboardType: UIKeyboardType { get set }
}
func initializeTextInputTraits(textInputTraits: UITextInputTraits) {
// We try to cast ('as?') to the UITextInputTraitsWithKeyboardType protocol
if let traitsWithKBType = textInputTraits as? UITextInputTraitsWithKeyboardType {
// if the cast succeeded, that means that the keyboardType property is implemented
// so we can access it on the casted variable
traitsWithKBType.keyboardType = .Default
}
// (and if the cast failed, this means that the property is not implemented)
}
我还演示了,如果你想要另一个例子,
< P>我会考虑做一个扩展,返回你的默认值,用于<代码> KiBooDype < /C>,让SETER不做任何事情。extension UITextInputTraits {
var keyboardType: UIKeyboardType {
get { return .default }
set { /* do nothing */ }
}
}
这样,您就可以从属性声明中删除可选的
protocol UITextInputTraits : NSObjectProtocol {
var keyboardType: UIKeyboardType { get set }
}
或者,如果您愿意,可以将其设置为可选的返回类型,var keyboardType:UIKeyboardType?
,并在扩展名中返回nil
,而不是。默认值
通过这种方式,您可以测试myObject.keyboardType==nil
以查看您的属性是否已实现。以下是我为实现Swift 2.2兼容性而提出的建议:
@objc protocol ComponentViewProtocol: class {
optional var componentModel: ComponentModelProtocol? { get set }
optional var componentModels: [String:ComponentModelProtocol]? { get set }
}
class ComponentView: NSObject, ComponentViewProtocol {
var componentModel: ComponentModelProtocol?
...
..
.
}
class SomeCodeThatUsesThisStuff {
func aMethod() {
if var componentModel = componentView.componentModel {
componentModel = .... (this succeeds - you can make assignment)
} else if var componentModels = componentView.componentModels {
componentModels = .... (this failed - no assignment possible)
}
}
}
本质上,您需要对可选属性执行“if/let绑定”,以确保它实际得到实现?如果它是nil,则封装对象没有实现它,但是您现在可以为它赋值,编译器将不再抱怨。这只是更改了您创建的局部变量-它不会更改对象值。我在Swift 2.2中尝试了这一点,但是as?我似乎记得,协议实际上是根据其名称进行评估的。如果核心对象还没有实现“uitePuttRaitsWithKeyboardType”,那么它就不会通过。想知道你是如何做到这一点的……从Swift 2.2到Swift 4到Swift 5.3.2仍然不可能
protocol UITextInputTraits : NSObjectProtocol {
var keyboardType: UIKeyboardType { get set }
}
@objc protocol ComponentViewProtocol: class {
optional var componentModel: ComponentModelProtocol? { get set }
optional var componentModels: [String:ComponentModelProtocol]? { get set }
}
class ComponentView: NSObject, ComponentViewProtocol {
var componentModel: ComponentModelProtocol?
...
..
.
}
class SomeCodeThatUsesThisStuff {
func aMethod() {
if var componentModel = componentView.componentModel {
componentModel = .... (this succeeds - you can make assignment)
} else if var componentModels = componentView.componentModels {
componentModels = .... (this failed - no assignment possible)
}
}
}