В чем разница между $ varName и _varName в SwiftUI - PullRequest
0 голосов
/ 25 сентября 2019

Когда вы работаете с оболочками свойств, у вас есть доступ как к $varName, так и к _varName, и я не вижу разницы.Например, здесь

import SwiftUI

struct ContentView: View {
    @Binding var varName: String

    var body: some View {
        TextField("", text: $varName) //here you can also use `_varName`
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView(varName: .constant("Hello world!"))
  }
}
#endif

вы можете использовать как $varName, так и _varName.Два решения кажутся эквивалентными.Обе переменные Binding<String>.Но если мне нужно что-то вроде этого:

import SwiftUI

struct ContentView: View {
    @Binding var varName: String

    init(varName: Binding<String>) {
        self.$varName = varName //ERROR
    }

    var body: some View {
        TextField("", text: $varName)
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView(varName: .constant("Hello world!"))
  }
}
#endif

Я получу ошибку:

Невозможно присвоить свойству: $ varName является неизменным

и я должен использовать _varName, чтобы подавить ошибку:

struct ContentView: View {
    @Binding var varName: String

    init(varName: Binding<String>) {
        self._varName = varName //this works fine
    }

    var body: some View {
        TextField("", text: _varName)
    }
}

Они по-прежнему оба Binding<String>, так почему же первое решение не будет работать?Согласно Apple (https://developer.apple.com/videos/play/wwdc2019/415/) компилятор превратит оболочку свойств в две вещи. Это:

@Binding var varName: String

становится:

//Compiler-synthesized code
var $varName = Binding<String> = Binding<String>()

public var varName: String {
    get { $varName.wrappedValue }

    set { $varName.wrappedValue = newValue }
} 

$varName должно быть var, так почему ошибка выше? И, прежде всего, что это _varName? Откуда она взялась?

1 Ответ

3 голосов
/ 25 сентября 2019

Синтезированное свойство _varName - это сохраняемое, устанавливаемое свойство, которое содержит (в вашем случае) экземпляр Binding<String>.

. Свойство varName сопоставляется со свойством wrappedValue оболочки.Binding объявляет wrappedValue следующим образом:

var wrappedValue: Value { get nonmutating set }

Поскольку wrappedValue объявлено с nonmutating set, синтезированное свойство varName всегдаустанавливается (даже если self не является изменяемым).

Синтезированное свойство $varName сопоставляется со свойством оболочки projectedValue, если оболочка имеет свойство projectedValue.Binding объявляет projectedValue следующим образом:

var projectedValue: Binding<Value> { get }

Поскольку projectedValue объявляется только get, а не get set, вы никогда не сможетеприсваивать $varName.

Binding не не нужно для предоставления свойства projectedValue, поскольку вы можете использовать _varName для получения объекта Binding<String>.Причина, по которой Binding объявляет свойство projectedValue, заключается в том, чтобы префикс $ работал для Binding так же, как и для State, ObservedObject и EnvironmentObject.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...