2017-10-02 17 views
7

Làm cách nào bạn có thể nhận được một giá trị chuỗi từ cú pháp Swift 4 smart keypaths (ví dụ: \Foo.bar)? Tại thời điểm này tôi tò mò về bất kỳ cách nào cả, không quan trọng nếu nó phức tạp.Lấy chuỗi từ cú pháp đường dẫn khóa mới 4 Swift?

Tôi thích ý tưởng về loại thông tin được liên kết với đường dẫn khóa thông minh. Nhưng không phải tất cả các API và bên thứ ba đều ở đó.

Có cách cũ để nhận chuỗi cho tên thuộc tính có xác thực thời gian biên dịch theo #keyPath(). Với Swift 4 để sử dụng #keyPath() bạn phải khai báo thuộc tính là @objc, đó là điều tôi muốn tránh.

Trả lời

5

Đối với các thuộc tính Mục tiêu-C trên các lớp Objective-C, bạn có thể sử dụng _kvcKeyPathString property để tải xuống.

Tuy nhiên, các đường dẫn khóa Swift có thể không có Tương đương chuỗi. Đó là một mục tiêu đã nêu của các đường dẫn khóa Swift mà chúng không yêu cầu tên trường được bao gồm trong tệp thực thi. Có thể một đường dẫn khóa có thể được biểu diễn dưới dạng một chuỗi các trường bù trừ của các trường để nhận hoặc đóng để gọi trên một đối tượng.

Tất nhiên, điều này trực tiếp xung đột với mục tiêu riêng của bạn về việc tránh khai báo các thuộc tính @objc. Tôi tin rằng không có thiết bị tích hợp để làm những gì bạn muốn làm.

+1

Rất thú vị! Tôi đã làm một bài kiểm tra nhanh ở đây và, thật không may, có vẻ như thuộc tính '_kvcKeyPathString' đã nói ở trên sẽ * chỉ * trả về giá trị không phải là nil cho các thuộc tính tiếp xúc' @ objc'. Ví dụ, cả hai đường dẫn khóa 'name' và' email', trong câu trả lời của tôi ở trên, được trả về trong 'nil'. –

+0

Lưu ý từ một câu hỏi liên quan: >> * Tuy nhiên, nếu bạn thêm thuộc tính '@ objc' vào thuộc tính thì' _kvcKeyPathString' sẽ thực sự có giá trị thay vì luôn là 'nil'. * << https: // stackoverflow.com/questions/46143292/is-it-possible-to-get-the-kvc-string-from-swift-4-keypath – pkamb

8

Câu trả lời ngắn gọn: bạn không thể. Tóm tắt KeyPath được thiết kế để đóng gói một đường dẫn khóa có khả năng lồng nhau từ một loại gốc đã cho. Do đó, việc xuất một giá trị String đơn lẻ có thể không có ý nghĩa trong trường hợp chung. Ví dụ:

Ví dụ: chuỗi được xuất theo giả thuyết có được hiểu là thuộc tính của loại gốc gốc hoặc là thành viên của một trong các thuộc tính của nó không? Ít nhất một mảng chuỗi cần phải được xuất để xử lý các trường hợp như vậy ...

Mỗi loại workaround. Có nói rằng, vì rằng KeyPath tuân theo giao thức Equatable, bạn có thể tự cung cấp giải pháp tùy chỉnh, cho mỗi loại. Ví dụ:

struct Auth { 
    var email: String 
    var password: String 
} 
struct User { 
    var name: String 
    var auth: Auth 
} 

cung cấp một phần mở rộng cho User con đường quan trọng dựa trên:

extension PartialKeyPath where Root == User { 
    var stringValue: String { 
     switch self { 
     case \User.name: return "name" 
     case \User.auth: return "auth" 
     case \User.auth.email: return "auth.email" 
     case \User.auth.password: return "auth.password" 
     default: fatalError("Unexpected key path") 
    } 
} 

sử dụng:

let name: KeyPath<User, String> = \User.name 
let email: KeyPath<User, String> = \User.auth.email 
print(name.stringValue) /* name */ 
print(email.stringValue) /* auth.email */ 

tôi sẽ không thực sự khuyên giải pháp này cho mã sản xuất, cho việc bảo dưỡng hơi cao, v.v .. Nhưng vì bạn tò mò điều này, ít nhất, cho bạn một con đường phía trước;)

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