SwiftUI вызывает мутирующую функцию из var body - PullRequest
4 голосов
/ 23 июня 2019

В уроке от Ray, за которым я следую, у меня установлены следующие свойства

struct ContentView : View {

    var rTarget = Double.random(in: 0..<1)
    var gTarget = Double.random(in: 0..<1)
    var bTarget = Double.random(in: 0..<1)
}

Они, конечно, неизменны, поэтому я не могу изменить их из функции, если я не отмечу эту функцию как мутирующую.

func reset() {
    rTarget = Double.random(in: 0..<1)
    gTarget = Double.random(in: 0..<1)
    bTarget = Double.random(in: 0..<1)
}

Cannot assign to property: 'self' is immutable

Но я называю эту функцию от var body

mutating func reset() {
    rTarget = Double.random(in: 0..<1)
    gTarget = Double.random(in: 0..<1)
    bTarget = Double.random(in: 0..<1)
}

fileprivate mutating func displayAlert() -> Alert {
    return Alert(title: Text("Your Score"), message: Text("\(computeScore())"), dismissButton: Alert.Button.destructive(Text("Ok"), onTrigger: {
        self.reset()
    }))
}

 var body: some View {
    Button(action: {
        self.showAlert = true
    }) {
        Text("Hit Me!")
        }.presentation($showAlert) {
            displayAlert()
    }
}

Cannot use mutating member on immutable value: 'self' is immutable

Но я не могупометить var body как mutating var

'mutating' may only be used on 'func' declarations

Итак, на этом этапе я хочу сбросить значения xTarget каждый раз, когда пользователь нажимает на кнопку оповещения, а яНе знаю, что будет хорошей практикой на этом этапе.

Ответы [ 3 ]

1 голос
/ 23 июня 2019

Трудно сказать, что рекомендуется в вашем случае, потому что в вашем примере вы не показываете, для чего фактически нужны целевые переменные.

Однако, я думаю, можно с уверенностью сказать, что в представлениях SwiftUI переменные, которые должны изменяться со временем, должны иметь либо @State, либо один из доступных вам типов привязки. В противном случае он, скорее всего, должен быть неизменным.

Все сводится к тому, чтобы определить, что является "источником истины". Если эти цели являются чем-то внутренним для представления, тогда используйте @State, если источник правды является внешним для представления, вы выбрали бы один из привязываемых параметров.

Я настоятельно рекомендую вам потратить 37 минут на просмотр WWDC2019, сессия 226 (поток данных через SwiftUI). Он прояснит все ваши вопросы по этому поводу.

Если вы спешите, переходите к 5:45. Но я рекомендую вам посмотреть все это. Со временем это сэкономит вам время.

Если вы не знаете, что такое «источник истины». Тогда вам обязательно стоит посмотреть сеанс.

1 голос
/ 23 июня 2019

Я работал над той же статьей.

У меня не было этой проблемы, потому что я уже использовал оболочку свойства @State.В соответствии с рекомендациями kontiki Session 226 (поток данных через SwiftUI) отлично подходит для понимания того, как использовать оболочку свойств при обновлении источника данных.

И если вы хотите знать, что@State этот ответ имеет все это.

Вот мой код:

@State var rTarget = Double.random(in: 0..<1)
@State var gTarget = Double.random(in: 0..<1)
@State var bTarget = Double.random(in: 0..<1)
@State var rGuess: Double
@State var gGuess: Double
@State var bGuess: Double
0 голосов
/ 23 июня 2019

Единственное решение, которое я нашел на данный момент, состоит в том, чтобы также пометить xTarget реквизиты как @State и изменить их, не изменяя функции

@State private var rTarget = Double.random(in: 0..<1)
@State private var gTarget = Double.random(in: 0..<1)
@State private var bTarget = Double.random(in: 0..<1)

Но мне не ясно, что это хорошая практика.

...