You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决‘非主Actor上下文传递NSItemProvider引发数据竞争’警告?

解决NSItemProvider非Sendable类型的并发警告

这个警告是因为NSItemProvider不属于Sendable类型,在非主Actor隔离的上下文里调用它的方法时,Swift并发运行时无法保证线程安全,可能引发数据竞争。以下是几种可行的解决方式:

方法1:将处理函数标记为主Actor隔离

NSItemProvider通常和UI操作绑定,直接把整个处理函数放到主Actor上下文,确保所有对它的访问都在主线程执行:

@MainActor
private func handleIncomingURL(itemProvider: NSItemProvider) async -> String? {
    do {
        // 推荐用Swift原生URL代替NSURL,更符合现代风格且是Sendable类型
        if let url = try await itemProvider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) as? URL { 
            if let urlString = url.absoluteString?.trimmingCharacters(in: .whitespacesAndNewlines), ShareViewController.isValidWebsiteURL(urlString) {
                return urlString
            }
        }
    } catch {
        print("Error handling incoming URL: \(error)")
    }
    return nil
}

@MainActor
private func handleIncomingText(itemProvider: NSItemProvider) async -> String? {
    do {
        let text = try await itemProvider.loadItem(forTypeIdentifier: UTType.text.identifier, options: nil) as? String
        if let text = text?.trimmingCharacters(in: .whitespacesAndNewlines) {
            do {
                let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
                let matches = detector.matches(
                    in: text,
                    options: [],
                    range: NSRange(location: 0, length: text.utf16.count)
                )
                for match in matches {
                    if let range = Range(match.range, in: text) {
                        let url = String(text[range]).trimmingCharacters(in: .whitespacesAndNewlines)
                        if ShareViewController.isValidWebsiteURL(url) {
                            return url
                        }
                    }
                }
            } catch let error {
                print("Do-Try Error: \(error.localizedDescription)")
            }
        }
    } catch {
        print("Error handling incoming text: \(error)")
    }
    return nil
}

方法2:仅在主Actor中访问NSItemProvider

如果不想让整个函数都在主Actor运行,可以只把调用loadItem的代码块切换到主Actor上下文:

private func handleIncomingURL(itemProvider: NSItemProvider) async -> String? {
    do {
        let url = await MainActor.run {
            try? await itemProvider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) as? URL
        }
        if let url = url, 
           let urlString = url.absoluteString?.trimmingCharacters(in: .whitespacesAndNewlines), 
           ShareViewController.isValidWebsiteURL(urlString) {
            return urlString
        }
    } catch {
        print("Error handling incoming URL: \(error)")
    }
    return nil
}

private func handleIncomingText(itemProvider: NSItemProvider) async -> String? {
    do {
        let text = await MainActor.run {
            try? await itemProvider.loadItem(forTypeIdentifier: UTType.text.identifier, options: nil) as? String
        }
        if let text = text?.trimmingCharacters(in: .whitespacesAndNewlines) {
            do {
                let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
                let matches = detector.matches(
                    in: text,
                    options: [],
                    range: NSRange(location: 0, length: text.utf16.count)
                )
                for match in matches {
                    if let range = Range(match.range, in: text) {
                        let url = String(text[range]).trimmingCharacters(in: .whitespacesAndNewlines)
                        if ShareViewController.isValidWebsiteURL(url) {
                            return url
                        }
                    }
                }
            } catch let error {
                print("Do-Try Error: \(error.localizedDescription)")
            }
        }
    } catch {
        print("Error handling incoming text: \(error)")
    }
    return nil
}

额外优化:用URL替代NSURL

NSURL是Objective-C兼容类型,本身也不是Sendable,换成Swift原生的URL不仅符合现代Swift编码风格,还能消除额外类型转换带来的潜在安全警告。


内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 15:57:04