Closed7
\.selfって何

ForEach(fruits, id: \.self) { fruit in
Text(fruit)
}
このようなコードで出てくる.selfが何者か気になったので調べる。

selfが何かから調べる
型内部では.selfを使うことでそのオブジェクト自身にアクセスすることができる。
Kotlinでいうところのthis。
struct Person {
let name: String
func greet() {
print("Hello. My name is \(name)")
// 同じこと
sayHi() // Hi!
self.sayHi() // Hi!
// 同じこと
print(name) // mtkw
print(self.name) // mtkw
// 自分自身をみる
print(self) // Person(name: "mtkw")
}
func sayHi() {
print("Hi!")
}
}
let person = Person(name: "mtkw")
person.greet()
print(person.self) // // Person(name: "mtkw")

selfは自分自身を表すことがわかった。
インスタンスのselfで自分自身にインスタンスにアクセスできる。
インスタンスメソッド内でselfを使うとインスタンス自体にアクセスできる。
\は何を意味しているのか?
キーパスというものらしい。
キーパス
変数へのアクセスにキーパスというものでアクセスできる。
struct Animal {
let name: String
func greet() {
print("Hi! My name is \(name)")
}
}
print(\Animal.name) // Swift.KeyPath<Main.Animal, Swift.String>
let rabbit = Animal(name: "rabbit")
print(rabbit[keyPath: \Animal.name]) // rabbit

struct Animal {
let name: String
func greet() {
print("Hi! My name is \(name)")
}
}
let nameKeyPath: KeyPath<Animal, String> = \.name
print(rabbit[keyPath: nameKeyPath])
このようにKeyPathのインスタンスを作ることもできる

\.self
というのはおそらく、selfへアクセスするためのキーパスであることがわかった。
なので以下のように書けるのかな?
struct View {
let name: String
func draw() {
let keyPath: KeyPath<View, View> = \.self
print(self[keyPath: keyPath])
}
}
View(name: "MainView").draw() // View(name: "MainView")

では元に戻ってSwiftUIのForEachに戻る。
public init(_ data: Data, id: KeyPath<Data.Element, ID>, @ViewBuilder content: @escaping (Data.Element) -> Content)
なぜ.selfで型が KeyPath<Data.Element, ID>に解決できるのか?
ForEach(fruits, id: \.self) { fruit in
Text(fruit)
}
ぱっと見だけど、\.self
だと、自分自身を参照するキーパすだから、fruitsのデータ自体を参照するためのキーパスに見える。つまりKeyPath<Data.Element, ID>ではなく、KeyPath<Data.Element, Data.Element>にならないのかな?と思った。

ちょっとこれ以上はよくわからなかったがChatGptによると以下らしい。
\.selfの型解決
\.selfは、要素自身が一意の識別子である場合に使います。この場合、\.selfはKeyPath<Data.Element, Data.Element>型ですが、実際にはForEachが期待するKeyPath<Data.Element, ID>型に自動的に変換されるようになっています。
このスクラップは2024/08/17にクローズされました