2014-09-28 26 views
14

Làm sao người ta thiết lập một tài sản không bắt buộc của một giao thức? Ví dụ: UITextInputTraits có một số thuộc tính đọc/ghi tùy chọn. Khi tôi cố gắng sau tôi nhận được một lỗi biên dịch (Không thể gán cho 'keyboardType' trong 'textInputTraits'):Swift: thiết lập một tài sản không bắt buộc của một giao thức

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

Thông thường khi truy cập vào một tài sản không bắt buộc của một giao thức bạn thêm một dấu hỏi nhưng điều này không làm việc khi gán một giá trị (lỗi: không thể gán cho là kết quả của biểu thức này):

textInputTraits.keyboardType? = .Default 

giao thức trông giống như: (? chưa)

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

Trả lời

9

Đó là không thể trong Swift . Tham chiếu từ một ADF thread:

Optional property requirements, and optional method requirements that return a value, will always return an optional value of the appropriate type when they are accessed or called, to reflect the fact that the optional requirement may not have been implemented.

So it's no surprise to get optional values easily. However, setting a property requires implementation to be guaranteed.

+0

Tuy nhiên không thể là của Swift 2.2 – adib

+0

Tuy nhiên không thể là của Swift 4 – Speakus

+0

Và đối với một lý do chính đáng. Sử dụng 'tùy chọn func setSomething (_ :)'. – akashivskyy

3

Một workaround là để tạo ra một giao thức phù hợp với người đầu tiên, nhưng điều đó tuyên bố rằng bất động sản bắt buộc như là bắt buộc. Sau đó, để cố gắng truyền đối tượng đó làm giao thức mới và nếu dàn diễn viên thành công, chúng tôi có thể truy cập trực tiếp thuộc tính.

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) 
} 

Tôi cũng chứng minh rằng at the bottom on this SO answer nếu bạn muốn một ví dụ khác về ý tưởng.

+0

Tôi đã thử với Swift 2.2, nhưng như thế nào? không được dùng - dường như tôi nhớ lại rằng các giao thức thực sự được đánh giá theo tên của chúng. Nếu đối tượng cốt lõi đã không thực hiện "UITextInputTraitsWithKeyboardType" thì nó sẽ không vượt qua. Tự hỏi làm thế nào bạn có để làm việc này ... –

6

Tôi muốn xem xét làm một phần mở rộng trở về giá trị mặc định cho keyboardType, và có setter không làm gì cả.

extension UITextInputTraits { 
    var keyboardType: UIKeyboardType { 
     get { return .Default } 
     set(new){ /* do nothing */ } 
    } 
} 

Bằng cách đó, bạn có thể xóa optional khỏi tuyên bố thuộc tính của mình.

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

Hoặc, nếu bạn thích, bạn có thể làm cho nó của kiểu trả về tùy chọn, var keyboardType: UIKeyboardType?, và trở nil thay vì .Default trong phần mở rộng của bạn.

Bằng cách này, bạn có thể kiểm tra cho myObject.keyboardType == nil để xem tài sản của bạn được thực hiện.

0

Sau đây là những gì tôi đã đưa ra cho Swift 2.2 tương thích:

@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) 
     } 
    } 
} 

Về bản chất bạn cần phải thực hiện một "nếu/hãy để ràng buộc" trên thuộc tính bắt buộc để đảm bảo nó thực sự được thực hiện? Nếu đó là con số không sau đó các đối tượng Encapsulating đã không thực hiện nó, nhưng nếu không bây giờ bạn có thể làm bài tập với nó và trình biên dịch sẽ không còn phàn nàn.

+0

chỉ này thay đổi một biến địa phương mà bạn thực hiện - nó không làm thay đổi giá trị các đối tượng. –

Các vấn đề liên quan