无法对不可变值使用变异 getter:'self' 是不可变错误
Cannot use mutating getter on immutable value: 'self' is immutable error
我正在尝试重用一段较旧的 Swift 代码,但出现错误“无法对不可变值使用变异 getter:'self' 是不可变错误”。 Xcode 想在 func 之前添加 'mutating',并提出通过 'fix' 来实现。所以错误在那里消失了,但仍然存在于 'Text' 语句中。
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) { [=12=] + .0 } / Double(points.count)
lazy var meanMW = points.reduce(0) { [=12=] + .1 } / Double(points.count)
lazy var a = points.reduce(0) { [=12=] + (.day - meanDays) * (.mW - meanMW) }
lazy var b = points.reduce(0) { [=12=] + pow(.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
因为在结构内部调用x
时,不清楚contentView
本身是否可变。值类型变得可变 只有当 它被定义为 var
.
因此,如果在结构内的构建器函数中使用它之前用不可变值包装它会有所帮助。
像这样:
func xValue() -> Double {
var mutatableSelf = self
return mutatableSelf.x
}
var body: some View {
VStack {
Text("\(xValue())")
}
}
注意:Lazy
属性 的值将在第一次调用时关联,这会改变对象。所以他们被认为是 mutating
一个getter不能变异
这主要是 Swift 的 getter 设计。原则是:
getter 不应改变对象。因为开发人员可能没有预料到这一点。他们应该只在您使用 setter 或调用 mutating 函数时才会发生变化。 A getter 两者都不是。
以下示例按预期工作:
struct Device {
var isOn = true
}
let x = Device()
let y = Device()
y.isOn // Doing such will not cause the object to mutate.
然而下面的例子,getter会有副作用。 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.
懒惰正在变异:
struct ContentView: View {
lazy var x : Double = 3.0
var body: some View {
Text("\(x)") // ERROR
}
}
将导致以下错误:
Cannot use mutating getter on immutable value: 'self' is immutable
SwiftUI - 特例
因为 body
变量是一个计算的 属性,你不能 mutate/set 变量。不过有办法解决这个问题。
用 @State
属性 包装标记变量。
例子。以下代码无法编译:
struct ContentView: View {
var currentDate = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
Text("\(currentDate)")
.onReceive(timer) { input in
currentDate = input // ERROR: Cannot assign to property: 'self' is immutable
}
}
}
然而下面的会,只是因为它有@State
struct ContentView: View {
@State var currentDate = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
Text("\(currentDate)")
.onReceive(timer) { input in
currentDate = input
}
}
}
有关更多信息,请参阅 here
我正在尝试重用一段较旧的 Swift 代码,但出现错误“无法对不可变值使用变异 getter:'self' 是不可变错误”。 Xcode 想在 func 之前添加 'mutating',并提出通过 'fix' 来实现。所以错误在那里消失了,但仍然存在于 'Text' 语句中。
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) { [=12=] + .0 } / Double(points.count)
lazy var meanMW = points.reduce(0) { [=12=] + .1 } / Double(points.count)
lazy var a = points.reduce(0) { [=12=] + (.day - meanDays) * (.mW - meanMW) }
lazy var b = points.reduce(0) { [=12=] + pow(.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
因为在结构内部调用x
时,不清楚contentView
本身是否可变。值类型变得可变 只有当 它被定义为 var
.
因此,如果在结构内的构建器函数中使用它之前用不可变值包装它会有所帮助。
像这样:
func xValue() -> Double {
var mutatableSelf = self
return mutatableSelf.x
}
var body: some View {
VStack {
Text("\(xValue())")
}
}
注意:Lazy
属性 的值将在第一次调用时关联,这会改变对象。所以他们被认为是 mutating
一个getter不能变异
这主要是 Swift 的 getter 设计。原则是:
getter 不应改变对象。因为开发人员可能没有预料到这一点。他们应该只在您使用 setter 或调用 mutating 函数时才会发生变化。 A getter 两者都不是。
以下示例按预期工作:
struct Device {
var isOn = true
}
let x = Device()
let y = Device()
y.isOn // Doing such will not cause the object to mutate.
然而下面的例子,getter会有副作用。 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.
懒惰正在变异:
struct ContentView: View {
lazy var x : Double = 3.0
var body: some View {
Text("\(x)") // ERROR
}
}
将导致以下错误:
Cannot use mutating getter on immutable value: 'self' is immutable
SwiftUI - 特例
因为 body
变量是一个计算的 属性,你不能 mutate/set 变量。不过有办法解决这个问题。
用 @State
属性 包装标记变量。
例子。以下代码无法编译:
struct ContentView: View {
var currentDate = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
Text("\(currentDate)")
.onReceive(timer) { input in
currentDate = input // ERROR: Cannot assign to property: 'self' is immutable
}
}
}
然而下面的会,只是因为它有@State
struct ContentView: View {
@State var currentDate = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
Text("\(currentDate)")
.onReceive(timer) { input in
currentDate = input
}
}
}
有关更多信息,请参阅 here