如何在保留==函数的同时,让Main Actor隔离的name属性可变?
解决Main Actor隔离类中可变属性与Equatable协议冲突的问题
当你把name从let改为var后,报错的核心原因是:@MainActor修饰的类中,所有属性默认属于Main Actor隔离上下文,而你原来的==函数是nonisolated(脱离Main Actor),无法直接访问受隔离的可变属性(Swift对可变隔离属性的访问约束更严格)。下面是两种可行的解决办法:
方案一:让==函数运行在Main Actor上下文
直接去掉==函数的nonisolated修饰,给它加上@MainActor,这样函数就能在Main Actor环境中访问所有隔离属性:
import SwiftUI @MainActor class DistanceProfile: Equatable { let uuid: String var name: String // 改为可变属性 let authorId: Int init(uuid: String, name: String, authorId: Int) { self.uuid = uuid self.name = name self.authorId = authorId } // Equatable:调整为Main Actor隔离的函数 static func == (lhs: DistanceProfile, rhs: DistanceProfile) -> Bool { return lhs.uuid == rhs.uuid && lhs.name == rhs.name && lhs.authorId == rhs.authorId } }
注意:调用这个==函数时,必须处于Main Actor上下文。如果在非Main Actor的代码中比较实例,需要用await,比如await profileA == profileB。
方案二:将用于比较的属性标记为nonisolated
如果不想限制==的调用上下文,可以把uuid、name、authorId都标记为nonisolated,让它们脱离Main Actor的隔离约束,这样nonisolated的==函数就能直接访问这些属性:
import SwiftUI @MainActor class DistanceProfile: Equatable { nonisolated let uuid: String nonisolated var name: String // 改为可变并标记nonisolated nonisolated let authorId: Int init(uuid: String, name: String, authorId: Int) { self.uuid = uuid self.name = name self.authorId = authorId } // Equatable:保持nonisolated不变 nonisolated static func == (lhs: DistanceProfile, rhs: DistanceProfile) -> Bool { return lhs.uuid == rhs.uuid && lhs.name == rhs.name && lhs.authorId == rhs.authorId } }
注意:nonisolated var的修改不再受Main Actor的线程安全保护,你需要自己确保修改操作只在Main Actor中进行,或者添加锁等机制避免多线程竞争问题。
内容的提问来源于stack exchange,提问作者Sergei Kirasirov
相关产品推荐
相关产品推荐

