Ошибка использования String(format:, args) с SwiftUI в Xcode11 Beta 4

После обновления до Xcode 11 Beta 4 я начал видеть ошибку при использовании String(format: , args) с участием @State свойство. Смотрите код ниже. второй Text строка выдает ошибку:

Тип выражения 'String' является неоднозначным без дополнительного контекста

пока Textс 1, 3 и 4 работают просто отлично.

struct ContentView : View {
    @State var selection = 2

    var body: some View {
        VStack {
            Text("My selection \(selection)") // works
            Text("My selection \(String(format: "%02d", selection))") // error
            Text("My selection \(String(format: "%02d", Int(selection)))") // works
            Text("My selection \(String(format: "%02d", $selection.binding.value))") // works
        }
    }
}

Я понимаю, что это бета-версия программного обеспечения, но мне было любопытно, если кто-нибудь может увидеть причину такого поведения, или это просто ошибка. Если это не может быть объяснено, я отправлю радар.

1 ответ

Решение

В бета-4 реализация оболочки свойств изменилась незначительно. В бета-3 ваш вид был переписан компилятором как:

internal struct ContentView : View {
  @State internal var selection: Int { get nonmutating set }
  internal var $selection: Binding<Int> { get }
  @_hasInitialValue private var $$selection: State<Int>
  internal var body: some View { get }
  internal init(selection: Int = 2)
  internal init()
  internal typealias Body = some View
}

в то время как на бета-версии 4 он делает это:

internal struct ContentView : View {
  @State @_projectedValueProperty($selection) internal var selection: Int { get nonmutating set }
  internal var $selection: Binding<Int> { get }
  @_hasInitialValue private var _selection: State<Int>
  internal var body: some View { get }
  internal init(selection: Int = 2)
  internal init()
  internal typealias Body = some View
}

Теперь я догадываюсь: это изменение затрудняет вывод компилятором типа вашей переменной? Обратите внимание, что другая альтернатива, которая работает, немного помогает компилятору, приводя selection as Int:

Text("My selection \(String(format: "%02d", selection as Int))")

Обновление (Xcode 11.2)

Я тоже получаю ошибку:

'inout Path' is not convertible to '@lvalue Path'

с этим кодом:

struct ContentView : View {
    @State var selection = 2

    var body: some View {
        VStack {
            Text(String(format: "%d", selection)) // does not work
        }
    }
}

Решено и добавление $ префикс, а затем доступ wrappedValue в String(format:, args:):

struct ContentView : View {
    @State var selection = 2

    var body: some View {
        VStack {
            Text(String(format: "%d", $selection.wrappedValue)) // works
        }
    }
}
Другие вопросы по тегам