假设我们有一个能够自我突变的结构,它必须作为后台操作的一部分发生:
struct Thing {
var something = 0
mutating func operation(block: () -> Void) {
// Start some background operation
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
// Mutate self upon background task completion
self.something += 1
block()
}
}
}
现在,当我在上下文中使用这样的结构时:
var myThing = Thing()
myThing.operation {
println(myThing.something)
}
println
给了我0
,好像myThing
从未发生变异。从self.something
内打印dispatch_async
显然会产生1
。
如何解决此问题,最好不必在self
竞争块中传递更新的结构operation
并覆盖主要上下文中的原始变量?
// Ew
var myThing = Thing()
myThing.operation {
(mutatedThing) in
myThing = mutatedThing
println(myThing.something)
}
答案 0 :(得分:6)
我添加了第二个答案,因为我的第一个答案解决了另一个问题。
我在与你几乎完全相同的情况下遇到了这种困难。
在工作和工作并努力找出正在发生的事情并修复它之后,我意识到问题基本上是使用了应该使用引用类型的值类型。
闭包似乎创建了结构的副本并对其进行操作,保持原始状态不变 - 这更符合值类型的行为。
另一方面,期望的行为是闭包中执行的动作由闭包之外的环境保留 - 换句话说,两个不同的上下文(在闭包内部和外部)需要引用相同的对象 - 更符合引用类型的行为。
长话短说,我把结构改成了一个类。问题消失了,不需要其他代码。
答案 1 :(得分:0)
我已多次看到这个确切的问题,但没有更详细的说明,我不能说它是否因为你正在使用它而发生。
直到我意识到派遣的行动发生在一个不合逻辑的时间,即通常之前当前时间,它才让我疯狂。在调度块的引用框架中,它正确更新了变量,这就是它从块内部正确打印出来的原因。但在“现实世界”中,由于某种原因,调度被认为从未发生过,价值变化被抛弃了。或者也许是因为变异隐含地创建了一个新的结构,并且因为它是“时间旅行”,所以它的引用永远不会更新。不能说。在我的情况下,一旦我正确安排了调度,问题就消失了。我希望有所帮助!