2014-06-07 27 views
19

Tôi đang viết lại lớp Objective-C trong Swift để cảm nhận ngôn ngữ. Trong Objective-C lớp học của tôi bao gồm các phương pháp sau đây:Làm cách nào để chuyển đổi từ điển NSD sang từ điển Swift <String, NSObject>?

- (id) initWithCoder:(NSCoder *)aDecoder 
{ 
    return [self initWithActionName:[aDecoder decodeObjectOfClass:[NSString class] forKey:@"actionName"] 
          payload:[aDecoder decodeObjectOfClass:[NSDictionary class] forKey:@"payload"] 
          timestamp:[aDecoder decodeObjectOfClass:[NSDate class] forKey:@"timestamp"]]; 
} 

Sau một số thử và sai với trình biên dịch, tôi cố gắng viết lại nó như thế này:

convenience init(aDecoder: NSCoder) { 
    let actionName = aDecoder.decodeObjectOfClass(NSString.self, forKey: "actionName") as NSString 
    let payload = aDecoder.decodeObjectOfClass(NSDictionary.self, forKey: "payload") as NSDictionary 
    let timestamp = aDecoder.decodeObjectOfClass(NSDate.self, forKey: "timestamp") as NSDate 
    self.init(actionName: actionName, payload: payload, timestamp: timestamp) 
} 

Tuy nhiên, đây vẫn mang lại cho tôi một lỗi trên dòng cuối cùng: “không thể tìm thấy một tình trạng quá tải cho init chấp nhận các đối số cung cấp” phương pháp chữ ký của init

init(actionName: String, payload: Dictionary<String, NSObject>, timestamp: NSDate) 

vì vậy tôi cho rằng vấn đề là tôi đang cố gắng chuyển một số NSDictionary thay vì Dictionary<String, NSObject>. Làm cách nào tôi có thể chuyển đổi giữa hai loại không tương đương này? Tôi có nên chỉ sử dụng NSDictionary cho tất cả mã có tương tác với các thành phần Objective-C khác không?

Trả lời

14

Giải mã từ điển của bạn là Dictionary<String, NSObject> thay vì NSDictionary.

let payload = aDecoder.decodeObjectOfClass(NSDictionary.self, forKey: "payload") as! Dictionary<String, NSObject> 

Vì bạn đang sử dụng Cocoa Touch để serialize và deserialize, họ serialized như NSDictionary, nhưng bạn có thể bỏ nó vào một Swift Dictionary<,>, theo WWDC 2014 trung gian Swiftnâng cao Swift video.

Bạn cũng có thể giải mã như NSDictionary và sau đó đúc một cách rõ ràng các đối tượng như sau:

self.init(actionName: actionName, payload: payload as! Dictionary<String, NSObject>, timestamp: timestamp) 

Về cơ bản, bạn đang chơi ở đây với hiệp phương sai/contravariance.

1

Bạn có chắc đó là tuyên bố chính xác cho init không? Thứ tự đối số khác với thứ tự bạn đang gọi trong mã Objective-C của bạn.

Vì vậy, nếu bạn muốn thực hiện lại chính xác, cuộc gọi cuối cùng có thể là self.init(actionName: actionName, timestamp: timestamp, payload: payload). Việc gọi trình khởi tạo với thứ tự các đối số sai sẽ dẫn đến chính xác thông báo lỗi mà bạn nhận được.

+0

Xin lỗi vì sự nhầm lẫn — vì tôi đã viết lại lớp, tôi đã quyết định tinh chỉnh API cùng một lúc. Thứ tự của các đối số cho phương thức Swift là chính xác, do đó, đó không phải là vấn đề. Tôi đã chỉnh sửa câu hỏi để thay đổi thứ tự của các đối số trong phiên bản ObjC để không có nhầm lẫn. – bdesham

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