1

我是 Swift 并发的新手(就像大多数人一样,我想),我遇到了一个编译器错误,我不知道该怎么办。


struct Thing {
  var counter = 0
  mutating func increment() async {
    counter += 1
  }
}

class Controller: UIViewController {
  var thing = Thing()
  
  func mutate() async {
    await thing.increment()
    print(thing.counter)
  }
}

let c = Controller()
Task {
  await c.mutate()
}

mutate()函数的第一行给了我以下错误。 Actor-isolated property 'thing' cannot be passed 'inout' to 'async' function call

如果我只是继承class而不是UIViewController正常工作,但我需要这里的控制器,所以我需要弄清楚如何在特定的上下文中使其工作。

4

1 回答 1

1

我认为问题出Thing在一个struct. 结构上的mutatingfunc 将为. 为了使它起作用,被视为调用中的参数。thingControllerthinginoutthing.increment()

如果您将事物actor设置为 a 而不是 astructincrement()不需要是 a mutating func,因此thing不会被视为inout参数。


一种可能的解决方法是首先制作结构的副本,然后在副本上调用变异函数,然后将其存储回控制器中的属性中。

func mutate() async {
    var thing = self.thing
    await thing.increment()
    self.thing = thing
    
    print(thing.counter)
}

这是一个问题的原因是 UIViewControllers 现在都是演员,所以属性被认为是演员隔离的。有一个nonisolated关键字,但它不能应用于存储的属性,所以它在这里似乎没有帮助。

如果控制器更改为actor,则错误消息会有所变化以说明这一点。

error: cannot call mutating async function 'increment()' on actor-isolated property 'thing'
        await thing.increment()
                    ^
于 2022-01-17T22:28:39.340 回答