应用程序的iCloud文档目录在重新安装应用程序后很难加载文件

时间:2017-07-06 10:46:35

标签: swift storage icloud

我试图在用户iCloud Drive上存储文件。 将文件保存到iCloud驱动器后,我可以检索它,只要我不重新安装应用程序。我将路径存储在NSUbiquitousKeyValueStore内的文件中。

保存文件的代码:

 let data = UIImagePNGRepresentation(finalImage)

        let filename = "sticker\((NSUbiquitousKeyValueStore.default().longLong(forKey: "stickerCount"))+1).png"
        let filenamePath = self.getDocumentsDirectory().appendingPathComponent(filename)
        NSUbiquitousKeyValueStore.default().set(NSUbiquitousKeyValueStore.default().longLong(forKey: "stickerCount")+1, forKey: "stickerCount")

        var filenames : NSMutableArray!
        if !(NSUbiquitousKeyValueStore.default().bool(forKey: "createdArray")){
            NSUbiquitousKeyValueStore.default().set(true, forKey: "createdArray")
            filenames = NSMutableArray()
        }else{
            filenames = (NSUbiquitousKeyValueStore.default().array(forKey: "fileNames")! as NSArray).mutableCopy() as! NSMutableArray
        }
        filenames.add(filename)
        NSUbiquitousKeyValueStore.default().set(filenames, forKey: "fileNames")
        NSUbiquitousKeyValueStore.default().synchronize()

        try? data?.write(to: filenamePath)

这是获取文件的代码:

func loadTheStickers() {
    stickerNames.removeAllObjects()
    stickers.removeAllObjects()
    var filenames : NSMutableArray!
    if !(NSUbiquitousKeyValueStore.default().bool(forKey: "createdArray")){
        NSUbiquitousKeyValueStore.default().set(true, forKey: "createdArray")
        filenames = NSMutableArray()
    }else{
        filenames = (NSUbiquitousKeyValueStore.default().array(forKey: "fileNames")! as NSArray).mutableCopy() as! NSMutableArray
    }
    for stickerName in filenames {
        stickerNames.add(stickerName)
        let url = getDocumentsDirectory().appendingPathComponent(stickerName as! String)
        stickers.add(url)
    }

}

我得到了URL,因此NSUbiquitousKeyValueStore正常工作,但是如果我重新安装应用程序,imageFromUrl将无法返回图像,因此它不存在。我只是使用这行代码:

cell.imageView.image = UIImage(contentsOfFile: (stickers[indexPath.row] as! URL).path)

并且在我尝试重新安装应用程序之前它再次完美。

这是我用来获取iCloud目录路径的类:

class CloudDataManager {

static let sharedInstance = CloudDataManager() // Singleton

struct DocumentsDirectory {
    static let localDocumentsURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupID)
    static let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: iCloudContainerID)?.appendingPathComponent("Documents")
}


// Return the Document directory (Cloud OR Local)
// To do in a background thread

func getDocumentDiretoryURL() -> URL {
    if isCloudEnabled()  {
        if !FileManager.default.fileExists(atPath: (DocumentsDirectory.iCloudDocumentsURL?.path)!){
            do {
            try FileManager.default.createDirectory(at: DocumentsDirectory.iCloudDocumentsURL!, withIntermediateDirectories: true, attributes: nil)
            }catch{
                NSLog("Error")
            }
        }
        NSLog("\(DocumentsDirectory.iCloudDocumentsURL!)")
        return DocumentsDirectory.iCloudDocumentsURL!
    } else {
        NSLog("\(DocumentsDirectory.localDocumentsURL!)")
        return DocumentsDirectory.localDocumentsURL!
    }
}

// Return true if iCloud is enabled

func isCloudEnabled() -> Bool {
    if DocumentsDirectory.iCloudDocumentsURL != nil { return true }
    else { return false }
}

// Delete All files at URL

func deleteFilesInDirectory(url: URL?) {
    let fileManager = FileManager.default
    let enumerator = fileManager.enumerator(atPath: url!.path)
    while let file = enumerator?.nextObject() as? String {

        do {
            try fileManager.removeItem(at: url!.appendingPathComponent(file))
            print("Files deleted")
        } catch let error as NSError {
            print("Failed deleting files : \(error)")
        }
    }
}

// Copy local files to iCloud
// iCloud will be cleared before any operation
// No data merging

func copyFileToCloud() {
    if isCloudEnabled() {
        deleteFilesInDirectory(url: DocumentsDirectory.iCloudDocumentsURL!) // Clear all files in iCloud Doc Dir
        let fileManager = FileManager.default
        let enumerator = fileManager.enumerator(atPath: (DocumentsDirectory.localDocumentsURL?.path)!)
        while let file = enumerator?.nextObject() as? String {

            do {
                try fileManager.copyItem(at: (DocumentsDirectory.localDocumentsURL?.appendingPathComponent(file))!, to: DocumentsDirectory.iCloudDocumentsURL!.appendingPathComponent(file))

                print("Copied to iCloud")
            } catch let error as NSError {
                print("Failed to move file to Cloud : \(error)")
            }
        }
    }
}

// Copy iCloud files to local directory
// Local dir will be cleared
// No data merging

func copyFileToLocal() {
    if isCloudEnabled() {
        deleteFilesInDirectory(url: DocumentsDirectory.localDocumentsURL)
        let fileManager = FileManager.default
        let enumerator = fileManager.enumerator(atPath: DocumentsDirectory.iCloudDocumentsURL!.path)
        while let file = enumerator?.nextObject() as? String {

            do {
                try fileManager.copyItem(at: DocumentsDirectory.iCloudDocumentsURL!.appendingPathComponent(file), to: (DocumentsDirectory.localDocumentsURL?.appendingPathComponent(file))!)

                print("Moved to local dir")
            } catch let error as NSError {
                print("Failed to move file to local dir : \(error)")
            }
        }
    }
}

}

并且我已经检查过,它会返回iCloud Document目录的正确URL。 所以我的问题是问题在哪里,我怎么能纠正代码,所以在重新安装应用程序或其他设备后文件是可用的,因为iCloud目录并不比简单地存储在本地Documents目录中好。

1 个答案:

答案 0 :(得分:1)

经过长时间的研究,我设法解决了这个问题。 您必须手动激活iCloud才能从云中下载项目,它会自动上传,但不会下载。

您必须对所有项目使用以下行:

FileManager.default.startDownloadingUbiquitousItem(at: url)

所以Appdelegates应用程序中的下载代码:didfinish ...方法现在看起来像这样:

  var filenames : NSMutableArray!
    if !(NSUbiquitousKeyValueStore.default().bool(forKey: "createdArray")){
        NSUbiquitousKeyValueStore.default().set(true, forKey: "createdArray")
        filenames = NSMutableArray()
    }else{
        filenames = (NSUbiquitousKeyValueStore.default().array(forKey: "fileNames")! as NSArray).mutableCopy() as! NSMutableArray
    }

    for stickerName in filenames {
        let url = getDocumentsDirectory().appendingPathComponent(stickerName as! String)
        if !FileManager.default.fileExists(atPath: url.path){
        do {
            try FileManager.default.startDownloadingUbiquitousItem(at: url)
        }catch{
            NSLog(error.localizedDescription)
        }
        }
    }
相关问题