Swift:设置协议的可选属性

时间:2014-09-28 09:13:29

标签: swift

如何设置协议的可选属性?例如,UITextInputTraits具有许多可选的读/写属性。当我尝试以下操作时出现编译错误(无法在'textInputTraits'中分配给'keyboardType'):

func initializeTextInputTraits(textInputTraits: UITextInputTraits) {
  textInputTraits.keyboardType = .Default
}

通常在访问协议的可选属性时添加问号但在分配值时不起作用(错误:无法分配给此表达式的结果):

textInputTraits.keyboardType? = .Default

协议如下:

protocol UITextInputTraits : NSObjectProtocol {
  optional var keyboardType: UIKeyboardType { get set }
}

4 个答案:

答案 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那么封装对象没有实现它,但是否则你现在可以对它进行赋值,编译器将不再抱怨。