雑誌を見てiCloud Documentの実験をしているのですが、実行エラーが発生して動作確認ができません。doc.save(to...の122行目です。
// // ViewController.swift // ICloudDemo // // Created by Comeluck on 2017/04/26. // Copyright © 2017年 Comeluck. All rights reserved. // import UIKit class ViewController: UIViewController{ // Documentに関する情報 struct USDocInfo { static let NAME = "usdoc_test" static let EXTENSION = "us" static var LOCAL_DOCUMENTS_PATH:String? = nil static var ICLOUD_CONTAINER_PATH:String? = nil } // アプリのサンドボックスのパスを格納する変数 var localDocumentsPath: String { if let dir = USDocInfo.LOCAL_DOCUMENTS_PATH { return dir } else { let dir = NSSearchPathForDirectoriesInDomains( .documentDirectory, .userDomainMask, true)[0] + "/" USDocInfo.LOCAL_DOCUMENTS_PATH = dir return dir } } var iCloudContainerPath: String? { return USDocInfo.ICLOUD_CONTAINER_PATH } var document: USDocument! var documentURL: URL { return document.fileURL } var isFileExists = false let query = NSMetadataQuery() // MARK: - Viewのライフサイクル override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. query.searchScopes = [ NSMetadataQueryUbiquitousDocumentsScope, NSMetadataQueryAccessibleUbiquitousExternalDocumentsScope] query.predicate = NSPredicate(format: "%K LIKE '*'", NSMetadataItemFSNameKey) DispatchQueue.global(qos: .default).async(execute: { if let url = FileManager.default.url(forUbiquityContainerIdentifier: nil) { print("iCloudコンテナのURL:\(url)") USDocInfo.ICLOUD_CONTAINER_PATH = url.path + "/Documents/" self.iCloudContainerDidInitialize() } }) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector: #selector(ViewController.iCloudDocumentDidChange(_:)), name: NSNotification.Name.UIDocumentStateChanged, object: self.document) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDocumentStateChanged, object: self.document) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // 非同期でのコンテナURL取得の結果として呼ばれます func iCloudContainerDidInitialize() { let filePath = iCloudContainerPath! + USDocInfo.NAME + "." + USDocInfo.EXTENSION let fileUrl = URL(fileURLWithPath: filePath) // ファイルの存在チェック isFileExists = FileManager.default.fileExists(atPath: filePath) if isFileExists { print("iCloudコンテナにDocumentデータがあります: \(filePath)") document = USDocument(fileURL:fileUrl) document.open(completionHandler: { (success:Bool) -> Void in if success { print("Documentを開きました。place: \(String(describing: self.document.place))") } else { print("Documentを開けませんでした。") } }) } else { print("iCloudコンテナにDocumentデータはありません。") // Documentを新規作成し、iCloudコンテナに保存 createDocument(fileUrl) // dispatch_async(dispatch_get_main_queue(), { // NSNotificationCenter.defaultCenter().addObserver(self, selector: "metadataQueryDidChange:", name: NSMetadataQueryDidFinishGatheringNotification, object: nil) // self.query.startQuery() // }) } } // func createDocument(_ fileUrl: URL?) { func createDocument(_ fileUrl: URL?) { let localFilePath = localDocumentsPath + USDocInfo.NAME + "." + USDocInfo.EXTENSION let localFileUrl = URL(fileURLWithPath : localFilePath) let doc = USDocument(fileURL : localFileUrl) doc.place = "自宅" print("自宅") doc.save(to: localFileUrl, for: .forCreating, completionHandler: { (success:Bool) in // "fatal error: unexpectedly found nil while unwrapping an Optional value" print("pass") if success {
以下続きます。
print("Documentデータを保存しました。") let error:NSError? = nil DispatchQueue.global(qos: .default).async { do{ try FileManager.default.setUbiquitous(true, itemAt: localFileUrl, destinationURL: fileUrl!) } catch let error { print("エラー内容:\(error)") } if success { print("iCloudコンテナへの移動に成功しました") } else { if let err = error { // print("iCloudコンテナへの移動に失敗しました: \(err.description)") print("iCloudコンテナへの移動に失敗しました: \(err.localizedDescription)") } } } } else { print("Documentデータを保存できませんでした。") } }) } // MARK: - Notification func metadataQueryDidChange(_ notification: Notification) { print("metadataQueryDidChange") query.stop() NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil) let metadataItems = query.results as! [NSMetadataItem] let urls = metadataItems.map({ (item: NSMetadataItem) -> URL in let url = item.value(forAttribute: NSMetadataItemURLKey) as! URL print("iCloud Storage: \(url)") return url }).filter({ (url: URL) -> Bool in if let fileName = url.path.components(separatedBy: "/").last { return fileName == USDocInfo.NAME + "." + USDocInfo.EXTENSION } else { return false } }) if 0 < urls.count { self.document = USDocument(fileURL: urls.first!) self.document.open(completionHandler: { (success:Bool) in if success { print("Documentを開きました。place: \(String(describing: self.document.place))") } else { print("Documentを開けませんでした。") } }) } else { print("該当ファイルがありません") } } func metadataQueryDidUpdate(_ notification: Notification) { print("metadataQueryDidUpdate") query.disableUpdates() var insertedURLs = [URL]() var removedURLs = [URL]() var updatedURLs = [URL]() let metadataItemToURLTransform: (NSMetadataItem) -> URL = { metadataItem in return metadataItem.value(forAttribute: NSMetadataItemURLKey) as! URL } let insertedMetadataItems = notification.userInfo?[NSMetadataQueryUpdateAddedItemsKey] as! [NSMetadataItem]? if let insertedMetadataItems = insertedMetadataItems { insertedURLs += insertedMetadataItems.map(metadataItemToURLTransform) } let removedMetadataItems = notification.userInfo?[NSMetadataQueryUpdateRemovedItemsKey] as! [NSMetadataItem]? if let removedMetadataItems = removedMetadataItems { removedURLs += removedMetadataItems.map(metadataItemToURLTransform) } let updatedMetadataItems = notification.userInfo?[NSMetadataQueryUpdateChangedItemsKey] as! [NSMetadataItem]? if let updatedMetadataItems = updatedMetadataItems { let completelyDownloadedUpdatedMetadataItems = updatedMetadataItems.filter { updatedMetadataItem in let downloadStatus = updatedMetadataItem.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as! String return downloadStatus == NSMetadataUbiquitousItemDownloadingStatusCurrent } updatedURLs += completelyDownloadedUpdatedMetadataItems.map(metadataItemToURLTransform) } query.enableUpdates() } func iCloudDocumentDidChange(_ notification: Notification) { if self.document.documentState.contains(.inConflict){ do{ try NSFileVersion.removeOtherVersionsOfItem(at: self.document.fileURL) } catch let error { print("エラー内容:\(error)") } if let conflicts = NSFileVersion.unresolvedConflictVersionsOfItem(at: self.document.fileURL){ for fileVersion in conflicts { fileVersion.isResolved = true } } } } }