转义闭包捕获变异 'self' 参数:struct
Escaping closure captures mutating 'self' parameter: struct
我有以下与 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
}
}
但是,我遇到了一个错误:
Escaping closure captures mutating 'self' parameter
我知道将结构更改为 class 可以解决这个问题,但是有什么方法可以在结构的转义闭包中实际捕获变异的自我吗?
我完成的解决方案:
import Foundation
import Combine
public final class IntervalTrigger: ObservableObject {
private let timeInterval: TimeInterval
@Published var value = false
public init(_ timeInterval: TimeInterval) {
self.timeInterval = timeInterval
}
public func toggle() {
value = true
let responseDate = Date().advanced(by: timeInterval)
OperationQueue.main.schedule(after: .init(responseDate)) { [weak self] in
self?.value = false
}
}
}
如您所见,快速解决方案是使用 引用类型 、class。但是为什么会这样呢?
Swift 结构是值类型,所以它们是不可变的。您可以将函数标记为 mutating
以向编译器指示函数会改变结构,但这实际上意味着什么?
考虑一个简单的结构:
struct Counter {
var count
init(_ count: Int = 0)
{
self.count = count
}
mutating func increment() {
self.count+=1
}
}
现在,尝试将其实例分配给 let
常量:
let someCounter = Counter()
someCounter.increment()
print(someCounter.count)
你会得到一个错误;你需要使用 var
.
var someCounter = Counter()
someCounter.increment()
print(someCounter.count)
当你调用一个 mutating
函数时实际发生的是一个 new Counter
被创建,新的 count
和它分配给 someCounter
。它实际上是在说 someCounter = Counter(someCounter.count+1)
现在,想想如果你可以在转义闭包中改变 self
会发生什么 - 新的 Counter
将在未来某个未指定的时间创建,但执行已经移动在。来不及更新了 someCounter
.
正如您所发现的,使用 class
的另一个优点是您可以使用 ObservableObject
,这使得更新 SwiftUI 视图变得更加容易.
我有以下与 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
}
}
但是,我遇到了一个错误:
Escaping closure captures mutating 'self' parameter
我知道将结构更改为 class 可以解决这个问题,但是有什么方法可以在结构的转义闭包中实际捕获变异的自我吗?
我完成的解决方案:
import Foundation
import Combine
public final class IntervalTrigger: ObservableObject {
private let timeInterval: TimeInterval
@Published var value = false
public init(_ timeInterval: TimeInterval) {
self.timeInterval = timeInterval
}
public func toggle() {
value = true
let responseDate = Date().advanced(by: timeInterval)
OperationQueue.main.schedule(after: .init(responseDate)) { [weak self] in
self?.value = false
}
}
}
如您所见,快速解决方案是使用 引用类型 、class。但是为什么会这样呢?
Swift 结构是值类型,所以它们是不可变的。您可以将函数标记为 mutating
以向编译器指示函数会改变结构,但这实际上意味着什么?
考虑一个简单的结构:
struct Counter {
var count
init(_ count: Int = 0)
{
self.count = count
}
mutating func increment() {
self.count+=1
}
}
现在,尝试将其实例分配给 let
常量:
let someCounter = Counter()
someCounter.increment()
print(someCounter.count)
你会得到一个错误;你需要使用 var
.
var someCounter = Counter()
someCounter.increment()
print(someCounter.count)
当你调用一个 mutating
函数时实际发生的是一个 new Counter
被创建,新的 count
和它分配给 someCounter
。它实际上是在说 someCounter = Counter(someCounter.count+1)
现在,想想如果你可以在转义闭包中改变 self
会发生什么 - 新的 Counter
将在未来某个未指定的时间创建,但执行已经移动在。来不及更新了 someCounter
.
正如您所发现的,使用 class
的另一个优点是您可以使用 ObservableObject
,这使得更新 SwiftUI 视图变得更加容易.