【问题标题】:Swift Keypath: How do I join them together and reference Arrays?Swift Keypath:如何将它们连接在一起并引用数组?
【发布时间】:2020-01-26 18:30:44
【问题描述】:

我想更好地了解 SWIFT 密钥路径,尤其是:

  1. 创建包含多个级别的键路径
  2. 创建下标为数组的键路径
  3. 将键路径连接在一起
  4. 了解键路径的类型

【问题讨论】:

  • 不清楚你在问什么,那是 4 个不同的问题吗?
  • 也许我的格式不适合这个。我花了几个小时才快速弄清楚关键路径。要弄清楚关键路径需要进行大量搜索 - 特别是问题 2 并不容易找到任何内容。我想在 Stack Overflow 上与其他人分享这个,所以我同时提问和回答——如果你愿意,可以提供 Keypaths 的迷你指南。我的动机是在其他人试图理解关键路径时为他们节省时间。也许在 Stack Overflow 上有更好的方法来做到这一点?

标签: arrays swift append keypaths


【解决方案1】:

让我们从这些结构开始:

struct Pet {
  var name: String
}

struct Address {
  var postcode: String
}

struct Person {
  var name: String
  var age: Int
  var address: Address
  var possessions: [String]
  var pets: [Pet]
}

还有这些变量:

let john = Person(
  name: "John",
  age: 50,
  address: Address(postcode: "BS1 9ZZ"),
  possessions: [ "Book",
                 "Laptop" ],
  pets: [ Pet(name: "Linga"),
          Pet(name: "Pharaoh") ]
)

let addresses: [Address] = [ Address(postcode: "ABC"),
                             Address(postcode: "DEF") ]

1) 创建包含多个级别的键路径

print("Field")
print(john[keyPath: \Person.name])         // John
print(john[keyPath: \Person.possessions])  // ["Book", "Laptop"]

print("Nested fields")
print(john[keyPath: \Person.address.postcode])  // BS1 9ZZ

2) 创建下标到数组中的键路径

print("Array lookup")
print(addresses[keyPath: \[Address][1] ])   // Address(postcode: "DEF")

print("Multilevel with array")
print(john[keyPath: \Person.possessions[1]])   // Laptop
print(john[keyPath: \Person.pets[0].name])     // Linga

print("Multilevel using normal indexing")
print(john[keyPath: \Person.possessions][1])               // Laptop
print(john[keyPath: \Person.pets][0][keyPath: \Pet.name])  // Linga

3) 将键路径连接在一起

print("Join keypaths")
let kp1: KeyPath<Person, Address> = \Person.address
let kp2: KeyPath<Address, String> = \Address.postcode
let kpboth = kp1.appending(path: kp2)
print(john[keyPath: kpboth])

print("Join keypaths including array")
let kpa = \Person.pets
let kpb = \[Pet][0]
let kpc = \Pet.name
let kpall = kpa.appending(path: kpb).appending(path: kpc)
print(john[keyPath: kpall])  // Linga

print("Join keypaths inline")
print(john[keyPath: (\Person.pets).appending(path: (\[Pet][0])).appending(path: (\Pet.name))])  // Linga

4) 了解键路径的类型

keypath 的类型是:

KeyPath<FromType, ToType>

FromType 是输入类型,ToType 是输出类型。

所以keypath的类型:\Person.pets是

KeyPath<Person, [Pet]>

因为这以 Person 开头并找到一组 Pets。

KeyPath 的类型:[Pet][0] 也是:

KeyPath<[Pet],Pet>

因为这从一个 Pets 数组开始并找到一个 Pet。

在加入 Keypaths 时,左侧 keypath 的输出类型必须与右侧 KeyPath 的输入类型匹配。 如果我们重复前面的示例但显示显式类型,我们可以清楚地看到这一点:

print("Join keypaths including array with Explicit Types")
let kpA: KeyPath<Person, [Pet] > = \Person.pets
let kpB: KeyPath<[Pet],  Pet   > = \[Pet][0]
let kpC: KeyPath<Pet,    String> = \Pet.name
let kpALL = kpA.appending(path: kpB).appending(path: kpC)
print(john[keyPath: kpALL])    // Linga

【讨论】:

    猜你喜欢
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多