SwiftUI中如何从Sendable闭包中使用@State属性?
SwiftUI中如何从Sendable闭包中使用@State属性?
嘿,这个问题我之前也踩过坑!Swift 6的actor隔离检查确实比Swift 5严格太多了,先给你捋明白为啥会出这个问题:你的hasComplexWave是@State属性,而SwiftUI视图的所有属性默认都是主actor隔离的——简单说就是只能在主线程/主actor上访问它。但visualEffect的闭包是@Sendable类型的,它要求捕获的变量要么是线程安全的Sendable类型,要么闭包本身就运行在对应的actor上,直接抓主actor隔离的属性自然就触发警告/错误了。
下面给你两种最靠谱的解决办法,你可以根据自己的代码风格选:
方法一:给闭包标记@MainActor
这是最直接的改法,明确告诉Swift这个闭包要在主actor上执行,这样就能安全访问主actor隔离的@State属性了:
view.visualEffect { @MainActor [hasComplexWave] content, proxy in content.distortionEffect( ShaderLibrary.complexWave( .float(startDate.timeIntervalSinceNow), .float2(proxy.size), .float(0.5), .float(8), .float(10) ), maxSampleOffset: CGSize(width: 100, height: 100), isEnabled: hasComplexWave ) }
这种方式改动最小,而且visualEffect这类视觉相关的闭包本来就该在主线程跑,完全符合预期。
方法二:先把属性值存到本地常量
如果你的场景里闭包不一定需要绑定主actor,或者想更清晰地隔离值的捕获,可以先在主actor环境下把hasComplexWave的值存成一个普通本地常量,再让Sendable闭包捕获这个常量——因为Bool是值类型,这个常量是线程安全的:
// 先在视图的主actor上下文里拿到属性值 let shouldEnableEffect = hasComplexWave view.visualEffect { [shouldEnableEffect] content, proxy in content.distortionEffect( ShaderLibrary.complexWave( .float(startDate.timeIntervalSinceNow), .float2(proxy.size), .float(0.5), .float(8), .float(10) ), maxSampleOffset: CGSize(width: 100, height: 100), isEnabled: shouldEnableEffect ) }
这种方法通用性更强,哪怕是处理其他值类型的@State/@Binding属性都能用,而且闭包不需要依赖主actor环境。
两种方法都能完美解决Swift 6的错误,选哪个全看你顺手~
备注:内容来源于stack exchange,提问作者johnrubythecat
相关产品推荐
相关产品推荐

