何时与演员的存储属性一起使用非隔离?

问题描述 投票:0回答:2

我不确定何时将

nonisolated
与演员的存储属性一起使用。

P.s 在此 blog 中,Douglas Gregor 提出了同样的问题“所以......总是需要非隔离的 let 来进行同步访问?”。但是我不明白他的回答。

谁能解释一下?

编辑:

澄清一下,正如博客中所写,使用 nonisolated 有助于在属性变为可变时摆脱未来的问题,但事实证明,任何不可变的属性都必须是 noniolsated,因为没有人知道他们的程序将如何改变随着时间的推移

swift actor swift-concurrency
2个回答
1
投票

属性(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 = ""
        }
    }
}
}

0
投票

你说:

正如博客中所写,如果属性变得可变,使用

nonisolated
有助于解决未来的问题

nonisolated let
没有解决这个问题。这是问题的根源。如果您使用
nonisolated let
,然后将其更改为
var
,这将需要重构同步访问此属性的外部代码,现在以异步方式执行此操作。这个对语言的提议更改暗示了一种潜在的机制来减轻这种情况。

具体来说,它建议即使在常量上没有

nonisolated
限定符,该模块仍然享有同步(非隔离)访问的好处。但它也建议在这个模块之外,它将保持隔离(虽然你不会喜欢那个同步接口,但这意味着随后引入的可变性不一定会破坏它的接口)。

虽然我很欣赏作者的意图,但正如您将在该线程中看到的那样,对这个提议的更改有一些反对。

你问:

我每次都需要用

nonisolated
let
吗?

这可能不是很好的建议。您应该只在满足以下两个条件的情况下使用

nonisolated let

  • 您有同步、非隔离访问的合法要求;和

  • 你有理由相信你不太可能让它可变和/或,如果你将来需要做这个改变,你(和任何其他使用这种类型的开发人员)愿意注册重构可能需要的运动。

一般来说,我们希望避免随着实现的发展而更改代码破坏接口。因此,在必要时,当然可以随意设置常量

nonisolated
,但除此之外,您可能希望避免这样做。

© www.soinside.com 2019 - 2024. All rights reserved.