swift 无法同步图像

ufj5ltwl  于 2023-04-19  发布在  Swift
关注(0)|答案(1)|浏览(171)

用户可以添加一个图像,其名称将存储在数据库中的“imagename”下。数据库将在用户的iPhone和示例iPad上同步。图像获得新的名称并保存。
这是一个函数:

private func saveImage() -> String? {
    guard let image = inputImage,
          let imageData = image.jpegData(compressionQuality: 0.5) else {
        return nil
    }
    
    let timestamp = Date().timeIntervalSince1970
    let imageName = "\(UUID().uuidString)-\(timestamp)"
    
    if let existingImageName = tool?.imagename {
        // Delete the existing image
        if let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents") {
            let existingImagePath = iCloudDocumentsURL.appendingPathComponent(existingImageName)
            try? FileManager.default.removeItem(at: existingImagePath)
        } else {
            let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let existingImagePath = documentsDirectory.appendingPathComponent(existingImageName)
            try? FileManager.default.removeItem(at: existingImagePath)
        }
    }
    
    var imagePath: URL
    if let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents") {
        // iCloud storage is available
        imagePath = iCloudDocumentsURL.appendingPathComponent(imageName)
    } else {
        // iCloud storage is not available, use local storage
        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        imagePath = documentsDirectory.appendingPathComponent(imageName)
    }
    
    do {
        try imageData.write(to: imagePath)
        print("Image saved with name: \(imageName)")
        return imageName
    } catch {
        print("Error saving image: \(error.localizedDescription)")
        return nil
    }
}

当我想查看图片时,我使用loadImage()函数:

func loadImage() {
    if let inputImage = inputImage {
        // An image has already been selected, so just display it
        self.inputImage = inputImage
    } else if let imageName = tool?.imagename {
        // Check both local and iCloud Documents directories for the image
        let localImagePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(imageName)

        var iCloudImagePath: URL?
        if let iCloudURL = FileManager.default.url(forUbiquityContainerIdentifier: nil) {
            iCloudImagePath = iCloudURL.appendingPathComponent("Documents").appendingPathComponent(imageName)
        }

        if FileManager.default.fileExists(atPath: localImagePath.path) {
            // Image exists in local directory, load it from there
            do {
                let imageData = try Data(contentsOf: localImagePath)
                inputImage = UIImage(data: imageData)
            } catch {
                print("Error loading image from local directory: \(error.localizedDescription)")
                inputImage = nil
            }
        } else if let iCloudImagePath = iCloudImagePath, FileManager.default.fileExists(atPath: iCloudImagePath.path) {
            // Image exists in iCloud Documents directory, load it from there
            do {
                let imageData = try Data(contentsOf: iCloudImagePath)
                inputImage = UIImage(data: imageData)
            } catch {
                print("Error loading image from iCloud Documents directory: \(error.localizedDescription)")
                inputImage = nil
            }
        } else {
            // Image not found in either directory
            inputImage = nil
        }
    } else {
        // No image selected
        inputImage = nil
    }
}

这是persistanceController:

struct PersistenceController {
    
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        do {

            try viewContext.save()

        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentCloudKitContainer

    
    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "HereIsTheContainerName")
        
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
    }
}

我可以保存图像并在本地系统上查看它。当我在iPad上查看imagename的值时,正确的名称就在那里,但图像不会被查看。看起来图像不会同步到iClouddrive。
这两种设备都为应用程序启用了“iCloud”和“iCloudDrive”选项。
你能找到我代码的错误吗?

bkhjykvo

bkhjykvo1#

我的假设是,为什么图像只能在本地可见,在saveImage()函数中,调用url(forUbiquityContainerIdentifier:)返回nil(根据文档:“如果无法定位容器,或者如果iCloud存储对于当前用户或设备不可用”),因此使用else语句,图像将保存在本地存储中(而不是iCloud容器内)。
注意:函数url(forUbiquityContainerIdentifier:)不依赖于网络连接,这意味着您可以将图像保存在容器中并让iOS同步它们。
设计提示:该函数不应该直接从主线程调用(使用类似www.example.com的东西DispatchQueue.global来检索URL)。
参考doc
func url(forUbiquityContainerIdentifier:)

重要

请勿从应用的主线程调用此方法。由于此方法可能需要花费大量时间来设置iCloud并返回请求的URL,因此您应始终从辅助线程调用它。要确定iCloud是否可用,尤其是在启动时,请检查ubiquityIdentityToken属性的值。
PS:如果你想强制下载看看startDownloadingUbiquitousItem(at:)和删除本地副本只evictUbiquitousItem(at:)

相关问题