Swift 4 smart keypaths 構文(\Foo.bar
など)からstring valueを取得する方法?この時点で、私はどんな方法にも興味がありますが、それが複雑であるかどうかは関係ありません。
型情報がスマートキーパスに関連付けられるというアイデアが好きです。しかし、すべてのAPIとサードパーティがまだ存在しているわけではありません。
#keyPath()
によるコンパイル時検証でプロパティ名の文字列を取得する古い方法があります。 Swift 4を使用して#keyPath()
を使用するには、プロパティを@objc
として宣言する必要がありますが、これは避けたいものです。
Objective-CクラスのObjective-Cプロパティには、 _kvcKeyPathString
property 取得します。
ただし、Swiftキーパスには文字列に相当するものがない場合があります。Swiftキーパスは、取得するフィールドのオフセットのシーケンス、またはオブジェクトを呼び出すクロージャーとして表すことができます。
もちろん、これはプロパティの宣言を避けるというあなた自身の目的と直接衝突します@objc
。私はあなたがやりたいことをするためのビルトイン機能がないと信じています。
簡単な答え:できません。 KeyPath
抽象化は、特定のルートタイプからの潜在的にネストされたプロパティキーパスをカプセル化するように設計されています。そのため、単一のString
値をエクスポートすることは、一般的なケースでは意味がない場合があります。
たとえば、仮想的にエクスポートされた文字列は、ルートタイプのプロパティまたはそのプロパティのいずれかのメンバーとして解釈されるべきですか?このようなシナリオに対処するには、少なくとも文字列配列をエクスポートする必要があります...
タイプごとの回避策。そうは言っても、KeyPath
がEquatable
プロトコルに準拠している場合、タイプごとにカスタムソリューションを提供できます。例えば:
struct Auth {
var email: String
var password: String
}
struct User {
var name: String
var auth: Auth
}
User
ベースのキーパスにextensionを指定します。
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")
}
}
使用法:
let name: KeyPath<User, String> = \User.name
let email: KeyPath<User, String> = \User.auth.email
print(name.stringValue) /* name */
print(email.stringValue) /* auth.email */
多少のメンテナンスが必要なため、本番用のコードにはこのソリューションをお勧めしません。しかし、少なくともこの方法に興味があるので、これから先への道があります;)
パーティーには少し遅れましたが、少なくともNSObjectサブクラスからキーパス文字列を取得する方法を見つけました。
NSExpression(forKeyPath: \UIView.bounds).keyPath
これはSwift 4拡張子として機能します:
extension AnyKeyPath {
/// Returns key path represented as a string
var asString: String? {
return _kvcKeyPathString?.description
}
}
使用法:
(\UIView.bounds).asString
// or
let keyPath = \UIView.bounds
keyPath.asString