我不确定何时将
nonisolated
与演员的存储属性一起使用。
P.s 在此 blog 中,Douglas Gregor 提出了同样的问题“所以......总是需要非隔离的 let 来进行同步访问?”。但是我不明白他的回答。
谁能解释一下?
编辑:
澄清一下,正如博客中所写,使用 nonisolated 有助于在属性变为可变时摆脱未来的问题,但事实证明,任何不可变的属性都必须是 noniolsated,因为没有人知道他们的程序将如何改变随着时间的推移
属性(let 或 computed var)和方法可以设为非隔离的,当你想让它们在 actor 外部访问时无需在调用它们时使用 await 关键字。我最近一直在看这个,这是一个很好的例子解释。
https://www.hackingwithswift.com/quick-start/concurrency/how-to-make-parts-of-an-actor-nonisolated
https://www.avanderlee.com/swift/nonisolated-isolated/
我用过我的 nonisolated 但在我刚刚运行的一个简单测试中,它似乎与 let 一起工作,无论是否非隔离。我确实注意到,当 let 未指定 nonisolated 时,我会在自动完成时收到警告,因此我一直指定 nonisolated。我预计未来可能会因为不指定而出现问题。
这是简单的代码,视图似乎在两种情况下都有效。
actor Foo {
nonisolated let test = "Test String"
}
class Bar: ObservableObject {
let foo = Foo()
@Published var localString: String = ""
func setString() {
// Accessing the nonisolated let. A warning is shown in auto complete
// if not specified nonisolated in autocompelte.
localString = foo.test
}
}
struct Test2: View {
@ObservedObject var bar = Bar()
var body: some View {
VStack {
Text("Bar local string = \(bar.localString)")
Button("Set") {
bar.setString()
}
Button("Clear") {
bar.localString = ""
}
}
}
}
你说:
正如博客中所写,如果属性变得可变,使用
有助于解决未来的问题nonisolated
nonisolated let
没有解决这个问题。这是问题的根源。如果您使用 nonisolated let
,然后将其更改为 var
,这将需要重构同步访问此属性的外部代码,现在以异步方式执行此操作。这个对语言的提议更改暗示了一种潜在的机制来减轻这种情况。
具体来说,它建议即使在常量上没有
nonisolated
限定符,该模块仍然享有同步(非隔离)访问的好处。但它也建议在这个模块之外,它将保持隔离(虽然你不会喜欢那个同步接口,但这意味着随后引入的可变性不一定会破坏它的接口)。
虽然我很欣赏作者的意图,但正如您将在该线程中看到的那样,对这个提议的更改有一些反对。
你问:
我每次都需要用
和nonisolated
吗?let
这可能不是很好的建议。您应该只在满足以下两个条件的情况下使用
nonisolated let
:
您有同步、非隔离访问的合法要求;和
你有理由相信你不太可能让它可变和/或,如果你将来需要做这个改变,你(和任何其他使用这种类型的开发人员)愿意注册重构可能需要的运动。
一般来说,我们希望避免随着实现的发展而更改代码破坏接口。因此,在必要时,当然可以随意设置常量
nonisolated
,但除此之外,您可能希望避免这样做。