Closed7

\.selfって何

mtkw0127mtkw0127
ForEach(fruits, id: \.self) { fruit in
    Text(fruit)
}

このようなコードで出てくる.selfが何者か気になったので調べる。

mtkw0127mtkw0127

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")
mtkw0127mtkw0127

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
mtkw0127mtkw0127
struct Animal {
    let name: String
    
    func greet() {
        print("Hi! My name is \(name)")
    }
}

let nameKeyPath: KeyPath<Animal, String> = \.name
print(rabbit[keyPath: nameKeyPath])

このようにKeyPathのインスタンスを作ることもできる

mtkw0127mtkw0127

\.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")
mtkw0127mtkw0127

では元に戻って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>にならないのかな?と思った。

mtkw0127mtkw0127

ちょっとこれ以上はよくわからなかったがChatGptによると以下らしい。

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