fix(concurrency): clear 4 Swift 6 warnings under default MainActor isolation
- ModelStore/FileVault: drop nonisolated(unsafe) on shared, mark all instance methods nonisolated (they only read filesystem); ModelKind enum also nonisolated - AIRuntime ↔ ModelStore cross-actor call resolved by the above - LLMSession: replace deprecated Device.setDefault(device:) with task-scoped Device.withDefaultDevice(.cpu, body:); wrap both load and generate so the TaskLocal propagates through ModelContainer.perform
This commit is contained in:
@@ -9,10 +9,9 @@ enum FileVaultError: Error {
|
||||
}
|
||||
|
||||
/// `@unchecked Sendable`:rootURL 是 let,方法只 I/O 到沙盒目录(线程安全),
|
||||
/// 可被任意 actor / Task 跨边界访问。
|
||||
/// `nonisolated(unsafe) shared`:见 ModelStore 同款注释。
|
||||
/// 可被任意 actor / Task 跨边界访问。实例方法显式 `nonisolated`,见 ModelStore 同款注释。
|
||||
final class FileVault: @unchecked Sendable {
|
||||
nonisolated(unsafe) static let shared: FileVault = {
|
||||
nonisolated static let shared: FileVault = {
|
||||
do {
|
||||
let appSupport = try FileManager.default.url(
|
||||
for: .applicationSupportDirectory,
|
||||
@@ -45,7 +44,7 @@ final class FileVault: @unchecked Sendable {
|
||||
|
||||
// MARK: - Path Safety
|
||||
|
||||
private func resolveSafePath(_ relativePath: String) throws -> URL {
|
||||
nonisolated private func resolveSafePath(_ relativePath: String) throws -> URL {
|
||||
guard !relativePath.contains("/"),
|
||||
!relativePath.contains(".."),
|
||||
!relativePath.isEmpty else {
|
||||
@@ -60,7 +59,7 @@ final class FileVault: @unchecked Sendable {
|
||||
|
||||
// MARK: - Public API
|
||||
|
||||
func writeJPEG(_ image: UIImage, quality: CGFloat = 0.85) throws -> SavedAsset {
|
||||
nonisolated func writeJPEG(_ image: UIImage, quality: CGFloat = 0.85) throws -> SavedAsset {
|
||||
guard let data = image.jpegData(compressionQuality: quality) else {
|
||||
throw FileVaultError.writeFailed
|
||||
}
|
||||
@@ -70,7 +69,7 @@ final class FileVault: @unchecked Sendable {
|
||||
return SavedAsset(relativePath: filename, bytes: data.count)
|
||||
}
|
||||
|
||||
func loadImage(relativePath: String) throws -> UIImage {
|
||||
nonisolated func loadImage(relativePath: String) throws -> UIImage {
|
||||
let url = try resolveSafePath(relativePath)
|
||||
let data: Data
|
||||
do {
|
||||
@@ -82,7 +81,7 @@ final class FileVault: @unchecked Sendable {
|
||||
return image
|
||||
}
|
||||
|
||||
func remove(relativePath: String) throws {
|
||||
nonisolated func remove(relativePath: String) throws {
|
||||
let url = try resolveSafePath(relativePath)
|
||||
do {
|
||||
try FileManager.default.removeItem(at: url)
|
||||
@@ -91,7 +90,7 @@ final class FileVault: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
func wipe() throws {
|
||||
nonisolated func wipe() throws {
|
||||
let fm = FileManager.default
|
||||
let contents = try fm.contentsOfDirectory(at: rootURL, includingPropertiesForKeys: nil)
|
||||
for url in contents {
|
||||
|
||||
Reference in New Issue
Block a user