2015-11-24 65 views
4

我目前在我的iOS應用程序中使用本地存儲。用戶數據存儲在文檔目錄中,現在我計劃使用iCloud Documents存儲。使用iCloud文檔存儲的最佳方式

這裏是我打算如何做到這一點:

  1. 察看的iCloud可用設備

  2. 如果是的話,請使用URLForUbiquityContainerIdentifier得到的iCloud容器URL

  3. 保存新文件和文件到這個新的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不可用,我擔心會發生問題,因此將使用本地目錄代替雲容器,並且將爲空。 謝謝。

+0

我使用與您相同的代碼來刪除iCloud文件,但該文件不會被刪除。我只是想確認您的刪除功能實際上適用於您的應用程序中的iCloud文件? – gbotha

+0

我沒有問題刪除我的應用程序中的iCloud文件。有時可能需要2分鐘才能看到文件已從iCloud容器中刪除。 – Romain

+1

謝謝。我發現刪除正在爲我工​​作。但是,當我嘗試更新已經在iCloud中的文件時,我最終得到一個具有相同名稱的新文件,後面跟着一個數字。於是,我決定先檢查文件是否在iCloud中,如果是,則刪除然後添加具有相同名稱的新文件。這仍然會導致重複被保存,並且原始文件在那裏(不被刪除)。但是,當我嘗試刪除文件時,它將被刪除。奇怪......不知道爲什麼會這樣。 – gbotha

回答

9

感謝上面的評論和更多的閱讀材料,我找到了解決我的問題的方法。

這裏是我決定這樣做:

  • 的iCloud將默認激活狀態(如果可能)
  • 用戶可以使用UISwitch在App
  • 禁用/啓用的iCloud
  • 當用戶禁用iCloud時,所有的iCloud文件將在本地傳輸
  • 當用戶啓用iCloud時,所有本地文件將在iCloud Ubiquity容器中傳輸
  • 沒有數據合併

像這樣的數據不會丟失。

我想幾乎每個人都會使用iCloud,一切都將是透明和無痛的。無論如何,我同步的文件很小,所以它應該工作得很好(到目前爲止它)。

我有5種simples方法:

  1. 方法檢查的iCloud可用
  2. 方法根據用戶的選擇(的iCloud或本地)
  3. 方法刪除所有返回的文檔URL目錄中的文件(應用程序使用的文件)
  4. 將文件從本地目錄移動到iCloud容器的方法
  5. 將方法從iCloud c ontainer到本地目錄

這裏是我的類處理有關問題

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)") 
      } 
     } 
    } 
} 



} 
+0

如果用戶碰巧關閉了您對iCloud的訪問權限,無論是通過禁用iCloud還是針對您的特定應用程序禁用iCloud,該應用程序如何知道如何將其文件移至本地(尤其是當其在後臺未打開時),還是他們滯留在iCloud? – SAHM

+0

文件未在iCloud中顯示任何特定問題。 –

1

檢查此鏈接:iCloud basics and code sample

如果你存儲的信息很簡單,最好使用NSUserDefaults的。你不想問iCloud的基本信息。

+0

謝謝,我使用UserDefaults來檢查用戶是否要使用iCloud。我正在通過檢查你給我的鏈接來調查更多。 – Romain

1

對於那些誰想要使用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)") 
       } 
      } 
     } 
    } 



} 
相關問題