Swift6重构:如何让UIActivity重写方法运行在@MainActor?
适配Swift6:解决SafariActivity的MainActor隔离问题
要解决UIApplication相关API的MainActor隔离报错,最直接的方案是将整个SafariActivity类标记为@MainActor,这样所有重写的UIActivity方法都会自动在主线程上下文执行,符合Swift6的并发安全要求。
修改后的完整代码如下:
import Foundation import UIKit @MainActor public final class SafariActivity: UIActivity { var url: URL? // MARK: - UIActivity Implementation public override var activityType: UIActivity.ActivityType { .openInSafari } public override var activityTitle: String? { "Open in Safari" } public override var activityImage: UIImage? { UIImage(systemName: "safari")?.applyingSymbolConfiguration(.init(scale: .large)) } public override func canPerform(withActivityItems activityItems: [Any]) -> Bool { // 优化判断逻辑,避免强制解包 activityItems.contains { item in guard let url = item as? URL else { return false } return UIApplication.shared.canOpenURL(url) } } public override func prepare(withActivityItems activityItems: [Any]) { // 用compactMap过滤出URL,再找到第一个可打开的 url = activityItems.compactMap { $0 as? URL }.first { UIApplication.shared.canOpenURL($0) } } public override func perform() { if let url = url { UIApplication.shared.open(url) } activityDidFinish(true) } } extension UIActivity.ActivityType { static let openInSafari = UIActivity.ActivityType(rawValue: "openInSafari") } extension UIActivity { @MainActor public static let openInSafari = SafariActivity() }
关键说明:
- 类级别的@MainActor标记:将
SafariActivity类标记为@MainActor后,所有属于该类的属性、方法都会自动纳入MainActor隔离上下文,重写的UIActivity方法自然也遵循这个规则,调用UIApplication.shared相关API时就不会再触发并发安全错误。 - 优化判断逻辑:把原代码中的强制解包
as! URL替换为可选绑定和compactMap,提升代码安全性,避免潜在的崩溃风险。 - 保持扩展的@MainActor:原UIActivity扩展中的
openInSafari静态属性已经标记了@MainActor,无需修改,确保实例创建在主线程上下文。
内容的提问来源于stack exchange,提问作者dual0j
相关产品推荐
相关产品推荐

