使用iCloud Documents Storage的最佳方式

时间:2015-11-24 06:27:56

标签: ios swift icloud

我目前在iOS应用中使用本地存储。用户数据存储在文档目录中,现在我计划使用iCloud Documents存储。

以下是我打算这样做的方法:

  1. 检查设备上是否有iCloud

  2. 如果是,请使用URLForUbiquityContainerIdentifier获取iCloud容器网址

  3. 将新文件和文档保存到此新网址

  4. 为此,我使用此代码将返回文档文件夹的URL(iCloud或本地)      

    class CloudDataManager {
    
        class func getDocumentDiretoryURL() -> NSURL {
            let localDocumentsURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: .UserDomainMask).last! as NSURL
            let iCloudDocumentsURL = NSFileManager.defaultManager().URLForUbiquityContainerIdentifier(nil)?.URLByAppendingPathComponent("Documents")
    
            if userDefault.boolForKey("useCloud") && iCloudDocumentsURL != nil  {
                return iCloudDocumentsURL!
            } else {
                return localDocumentsURL
            }
        }
    }
    

    这是最佳做法吗? 如果有一天iCloud不可用,我担心会出现问题,因此将使用本地目录而不是云容器,并且将为空。 谢谢。

3 个答案:

答案 0 :(得分:12)

感谢上面的评论和进一步的阅读,我找到了解决问题的方法。

以下是我决定这样做的方法:

  • 默认情况下会激活iCloud(如果可能)
  • 用户可以使用UISwitch在App
  • 中禁用/启用iCloud
  • 当用户禁用iCloud时,所有iCloud文件将在本地传输
  • 当用户启用iCloud时,所有本地文件都将在iCloud Ubiquity容器中传输
  • 无数据合并

像这样的数据不会丢失。

我猜几乎每个人都会使用iCloud,一切都会透明无痛。无论如何,我同步的文件非常小,所以它应该可以正常工作(到目前为止)。

我有5种简单方法:

  1. 检查iCloud是否可用的方法
  2. 根据用户选择(iCloud OR Local)
  3. 返回文档URL的方法
  4. 删除目录中所有文件的方法(应用程序使用的文件)
  5. 将文件从本地目录移动到iCloud容器的方法
  6. 将fies从iCloud容器移动到本地目录的方法
  7. 这是我的班级来处理问题

    class CloudDataManager {
    
    static let sharedInstance = CloudDataManager() // Singleton
    
    struct DocumentsDirectory {
        static let localDocumentsURL: NSURL? = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: .UserDomainMask).last! as NSURL
       static let iCloudDocumentsURL: NSURL? = NSFileManager.defaultManager().URLForUbiquityContainerIdentifier(nil)?.URLByAppendingPathComponent("Documents")
    
    }
    
    
    // Return the Document directory (Cloud OR Local)
    // To do in a background thread
    
    func getDocumentDiretoryURL() -> NSURL {
        print(DocumentsDirectory.iCloudDocumentsURL)
        print(DocumentsDirectory.localDocumentsURL)
        if userDefault.boolForKey("useCloud") && isCloudEnabled()  {
            return DocumentsDirectory.iCloudDocumentsURL!
        } else {
            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: NSURL?) {
        let fileManager = NSFileManager.defaultManager()
        let enumerator = fileManager.enumeratorAtPath(url!.path!)
        while let file = enumerator?.nextObject() as? String {
    
            do {
                try fileManager.removeItemAtURL(url!.URLByAppendingPathComponent(file))
                print("Files deleted")
            } catch let error as NSError {
                print("Failed deleting files : \(error)")
            }
        }
    }
    
    // Move local files to iCloud
    // iCloud will be cleared before any operation
    // No data merging
    
    func moveFileToCloud() {
        if isCloudEnabled() {
            deleteFilesInDirectory(DocumentsDirectory.iCloudDocumentsURL!) // Clear destination
            let fileManager = NSFileManager.defaultManager()
            let enumerator = fileManager.enumeratorAtPath(DocumentsDirectory.localDocumentsURL!.path!)
            while let file = enumerator?.nextObject() as? String {
    
                do {
                    try fileManager.setUbiquitous(true,
                        itemAtURL: DocumentsDirectory.localDocumentsURL!.URLByAppendingPathComponent(file),
                        destinationURL: DocumentsDirectory.iCloudDocumentsURL!.URLByAppendingPathComponent(file))
                    print("Moved to iCloud")
                } catch let error as NSError {
                    print("Failed to move file to Cloud : \(error)")
                }
            }
        }
    }
    
    // Move iCloud files to local directory
    // Local dir will be cleared
    // No data merging
    
    func moveFileToLocal() {
        if isCloudEnabled() {
            deleteFilesInDirectory(DocumentsDirectory.localDocumentsURL!)
            let fileManager = NSFileManager.defaultManager()
            let enumerator = fileManager.enumeratorAtPath(DocumentsDirectory.iCloudDocumentsURL!.path!)
            while let file = enumerator?.nextObject() as? String {
    
                do {
                    try fileManager.setUbiquitous(false,
                        itemAtURL: DocumentsDirectory.iCloudDocumentsURL!.URLByAppendingPathComponent(file),
                        destinationURL: DocumentsDirectory.localDocumentsURL!.URLByAppendingPathComponent(file))
                    print("Moved to local dir")
                } catch let error as NSError {
                    print("Failed to move file to local dir : \(error)")
                }
            }
        }
    }
    
    
    
    }
    

答案 1 :(得分:2)

点击此链接:iCloud basics and code sample

如果您存储的信息很简单,那么使用NSUserDefaults会更好。您不想向iCloud询问基本信息。

答案 2 :(得分:2)

对于那些想要使用 SWIFT 3 的人: 注意:我只是复制而不是移动数据。但是在复制数据之前清除目标路径..

class CloudDataManager {

    static let sharedInstance = CloudDataManager() // Singleton

    struct DocumentsDirectory {
        static let localDocumentsURL = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: .userDomainMask).last!
        static let iCloudDocumentsURL = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents")
    }


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

    func getDocumentDiretoryURL() -> URL {
        if isCloudEnabled()  {
            return DocumentsDirectory.iCloudDocumentsURL!
        } else {
            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)")
                }
            }
        }
    }



}