如何设置协议的可选属性?例如,UITextInputTraits具有许多可选的读/写属性。当我尝试以下操作时出现编译错误(无法在'textInputTraits'中分配给'keyboardType'):
func initializeTextInputTraits(textInputTraits: UITextInputTraits) {
textInputTraits.keyboardType = .Default
}
通常在访问协议的可选属性时添加问号但在分配值时不起作用(错误:无法分配给此表达式的结果):
textInputTraits.keyboardType? = .Default
协议如下:
protocol UITextInputTraits : NSObjectProtocol {
optional var keyboardType: UIKeyboardType { get set }
}
答案 0 :(得分:9)
在Swift中不可能(但是?)。引自ADF thread:
可选属性要求和返回值的可选方法要求,在访问或调用时始终返回相应类型的可选值,以反映可选要求可能尚未实施。
因此轻松获得可选值并不奇怪。但是,设置属性需要实现保证。
答案 1 :(得分:6)
我考虑将扩展程序返回keyboardType
的默认值,并让setter不执行任何操作。
extension UITextInputTraits {
var keyboardType: UIKeyboardType {
get { return .Default }
set(new){ /* do nothing */ }
}
}
这样您就可以从属性声明中删除optional
。
protocol UITextInputTraits : NSObjectProtocol {
var keyboardType: UIKeyboardType { get set }
}
或者,如果您愿意,可以使用可选的返回类型var keyboardType: UIKeyboardType?
,并在您的扩展程序中返回nil
而不是.Default
。
这样,您可以测试myObject.keyboardType == nil
以查看您的媒体资源是否已实施。
答案 2 :(得分:3)
一种解决方法是创建符合第一个协议的另一个协议,但是声明该可选属性是必需的。然后尝试将对象转换为新协议,如果转换成功,我们可以直接访问该属性。
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)
}
如果你想要另一个想法的例子,我也证明了at the bottom on this SO answer。
答案 3 :(得分:-1)
以下是我为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 binding”以确保它实际实现?如果它是nil那么封装对象没有实现它,但是否则你现在可以对它进行赋值,编译器将不再抱怨。