I have the following code I’m using with SwiftUI:
import Foundation
public struct Trigger {
public var value = false
public mutating func toggle() {
value = true
let responseDate = Date().advanced(by: 3)
OperationQueue.main.schedule(after: .init(responseDate)) {
moveBack()
}
}
private mutating func moveBack() {
value = false
}
}
However, I’m getting an error:
Escaping closure captures mutating ‘self’ parameter
I understand that changing the struct to a class would solve this issue, but is there any way to actually capture a mutating self in an escaping closure in a struct?
2
Answers
Solution I finished with:
As you have found, the quick solution is to use a reference type, a class. But why is this the case?
Swift structs are value types, so they are immutable. You can mark a function as
mutating
to indicate to the compiler that a function mutates the struct, but what does that actually mean?Consider a simple struct:
Now, try and assign an instance of this to a
let
constant:You will get an error; you need to use a
var
.What actually happens when you call a
mutating
func is that a newCounter
is created, with the newcount
and it is assigned tosomeCounter
. It is effectively sayingsomeCounter = Counter(someCounter.count+1)
Now, think what would happen if you could mutate
self
in an escaping closure – That newCounter
is going to be created at some unspecified time in the future, but execution has already moved on. It is too late to updatesomeCounter
.The other advantage of using a
class
, as you have found, is that you can useObservableObject
, which makes updating your SwiftUI views much easier.