2017-07-06 78 views
0

我试图将文件存储在用户iCloud驱动器。 将文件保存在其iCloud驱动器中后,只要我不重新安装应用程序,就可以检索它。我将路径存储到NSUbiquitousKeyValueStore中的文件。应用程序的iCloud文档目录失败后重新安装应用程序加载文件

代码来保存文件:

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

} 

而且我得到的网址,所以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)") 
      } 
     } 
    } 
} 

}

和我检查,它返回正确的URL中的iCloud文档目录。 所以我的问题是问题在哪里,我如何纠正代码,因此重新安装应用程序或其他设备后,文件是availabla,因为atm iCloud目录不比简单地存储在本地Documents目录更好。

回答

0

经过长期的研究,我设法解决了这个问题。 您必须手动激发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) 
     } 
     } 
    } 
相关问题