我试图在用户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目录中好。
答案 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)
}
}
}