Невозможно использовать изменяющийся метод получения для неизменяемого значения: 'self' - неизменная ошибка

Я пытаюсь повторно использовать старую часть кода Swift, но получаю сообщение об ошибке «Невозможно использовать изменяющийся метод получения для неизменяемого значения:« self »является неизменной ошибкой». Xcode хотел добавить «изменение» перед функцией и предложил сделать это с помощью «исправления». Таким образом, ошибка исчезла, но осталась в операторах «Текст».

import SwiftUI

struct ContentView: View {

     typealias PointTuple = (day: Double, mW: Double)
    let points: [PointTuple] = [(0.0, 31.98), (1.0, 31.89), (2.0, 31.77), (4.0, 31.58), (6.0, 31.46)]

    lazy var meanDays = points.reduce(0) { $0 + $1.0 } / Double(points.count)
    lazy var meanMW   = points.reduce(0) { $0 + $1.1 } / Double(points.count)

    lazy var a = points.reduce(0) { $0 + ($1.day - meanDays) * ($1.mW - meanMW) }
    lazy var b = points.reduce(0) { $0 + pow($1.day - meanDays, 2) }

    lazy var m = a / b
    lazy var c = meanMW - m * meanDays        
    lazy var x : Double = bG(day: 3.0)
    lazy var y : Double = bG(day: 5.0)
    lazy var z : Double = bG(day: 7.0)

    mutating func bG(day: Double) -> Double {
        return m * day + c
    }

    var body: some View {
        VStack {
            Text("\(x)")
            Text("\(y)")
            Text("\(z)")
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

person arakweker    schedule 01.08.2019    source источник
comment
Обходное решение, которое я нашел для этой проблемы, - использовать вычисляемые свойства вместо ленивых переменных. Однако я не понимаю, почему я не могу использовать ленивые вары, и я не понимаю предлагаемое решение   -  person charel-f    schedule 09.11.2019
comment
@ charel-f Я написал новый ответ. Пожалуйста, взгляните   -  person Honey    schedule 11.02.2020
comment
Спасибо, ваш новый ответ очень краток и понятен   -  person charel-f    schedule 13.02.2020


Ответы (2)


Потому что, когда вы вызываете x внутри структуры, еще не ясно, является ли contentView изменяемым или нет. Фактически, тип значения становится изменяемым только когда он определен как var.

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

нравится:

func xValue() -> Double {
    var mutatableSelf = self
    return mutatableSelf.x
}

var body: some View {
    VStack {
        Text("\(xValue())")
    }
}
person Mojtaba Hosseini    schedule 01.08.2019

Это не имеет ничего общего с SwiftUI. Речь идет о дизайне, который Swift обеспечивает своими геттерами. Принцип такой:

Получатели не должны изменять объект. Потому что разработчики могут не ожидать этого. Им следует ожидать изменений только тогда, когда вы используете сеттер или вызываете функцию mutating. Геттер - никто из них.

Следующий пример работает должным образом:

struct Device {
    var isOn = true
}

let x = Device()
let y = Device()

y.isOn // Doing such will not cause the object to mutate.

Однако в следующем примере геттер будет иметь побочный эффект. Архитектура Swift просто не позволяет этого.

struct Device2 {

    var x = 3
    var isOn: Bool {
        x = 5
        return true
    }
}

let a = Device2()
let b = Device2()

a.isOn // Doing such will mutate the object. a.x will be '5'. While `b.x` will be '3'. Swift doesn't want to allow this.
person Honey    schedule 11.02.2020
comment
Это помогло мне понять, что ленивое свойство изменяет объект при первом вызове и поэтому всегда будет рассматриваться как mutating. Это прискорбно, но, по крайней мере, сейчас это имеет смысл. - person Sebastien Martin; 22.04.2020