2016-05-09 4 views
3

私はUIDocumentPickerViewControllerを使用して、iCloud Driveからバックエンドにアップロードするファイルを選択させます。UIDocumentPickerViewControllerは存在しないファイルにURLを返します

ほとんどの場合、正常に動作します。しかし、時々(特にインターネット接続が不安定な場合)、documentPicker:didPickDocumentAtURL:はファイルシステム上に実際に存在しないURLを与え、それを使用しようとするとNSError "No such file or directory"を返します。

これを処理する正しい方法は何ですか?私はNSFileManager fileExistsAtPath:を使用することを考えていて、存在しなければ再度試してみるようユーザーに指示します。しかし、それは非常にユーザーフレンドリーではありません。 iCloudドライブの実際のエラー原因を取得し、iCloudドライブに再試行するよう指示する方法はありますか?

コードの関連部分:

@IBAction func add(sender: UIBarButtonItem) { 
    let documentMenu = UIDocumentMenuViewController(
     documentTypes: [kUTTypeImage as String], 
     inMode: .Import) 

    documentMenu.delegate = self 
    documentMenu.popoverPresentationController?.barButtonItem = sender 
    presentViewController(documentMenu, animated: true, completion: nil) 
} 

func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) { 
    documentPicker.delegate = self 
    documentPicker.popoverPresentationController?.sourceView = self.view 
    presentViewController(documentPicker, animated: true, completion: nil) 
} 

func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) { 
    print("original URL", url) 

    url.startAccessingSecurityScopedResource() 

    var error: NSError? 
    NSFileCoordinator().coordinateReadingItemAtURL(
    url, options: .ForUploading, error: &error) { url in 
     print("coordinated URL", url) 
    } 

    if let error = error { 
     print(error) 
    } 

    url.stopAccessingSecurityScopedResource() 
} 

私はiPhone上でOS Xと開口部にそれらの一つだけ(a synced file.bmp)上のiCloudドライブに二つの大きな画像(〜5MiBそれぞれ)を追加することでこれを再現し、もう一方は開かない(an unsynced file.bmp)。その後、WiFiをオフにします。それから私は自分のアプリケーションでそれらを選択しようとしました:

同期ファイル:

original URL file:///private/var/mobile/Containers/Data/Application/CE70EE57-B906-4BF8-B351-A57110BE2B01/tmp/example.com.demo-Inbox/a%20synced%20file.bmp 
coordinated URL file:///private/var/mobile/Containers/Data/Application/CE70EE57-B906-4BF8-B351-A57110BE2B01/tmp/CoordinatedZipFileDR7e5I/a%20synced%20file.bmp 

同期されていないファイル:

original URL file:///private/var/mobile/Containers/Data/Application/CE70EE57-B906-4BF8-B351-A57110BE2B01/tmp/example.com.demo-Inbox/an%20unsynced%20file.bmp 
Error Domain=NSCocoaErrorDomain Code=260 "The file “an unsynced file.bmp” couldn’t be opened because there is no such file." UserInfo={NSURL=file:///private/var/mobile/Containers/Data/Application/CE70EE57-B906-4BF8-B351-A57110BE2B01/tmp/example.com.demo-Inbox/an%20unsynced%20file.bmp, NSFilePath=/private/var/mobile/Containers/Data/Application/CE70EE57-B906-4BF8-B351-A57110BE2B01/tmp/example.com.demo-Inbox/an unsynced file.bmp, NSUnderlyingError=0x15fee1210 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}} 
+0

私は、UIDocumentPickerViewControllerを使用してGoogleドライブから画像をインポートする際に同様の問題が発生しています。有効な見た目のURLが返されますが、fileExistsAtPathはnilを返します(ただし散発的にしか発生しません)。インポートモードを使用する必要がありますが、Openモードに切り替えると問題が解決しないようです。また、OpenまたはMoveモードを使用する場合は、startAccessingSecurityScopedResourceを呼び出すだけでよいと考えています。私のテストでは、インポートモードを使用すると、その呼び出しは常にfalseを返します。投稿してからこれ以上の進歩はありませんか? – grfryling

+0

@grfrylingあいまいなエラーメッセージをユーザーに伝えて解決しました。私はオープンモードを試しましたが、存在しないURLを["ユビキタス"機能](https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index)で使用できることがわかりました.html#// apple_ref/doc/uid/20000305-SW76)。例えば、 'startDownloadingUbiquitousItemAtURL:error:'などです。しかし、DropboxはOpenモードをサポートしていないので、私はそれを使用しませんでした。 – imgx64

答えて

1

私は同じ問題を抱えていたが、それは私が削除された判明しました表示されているTempディレクトリが表示されました。だから、それが表示され、正しくdocumentPickerを呼び出すときに削除を保存します:didPickDocumentAtURL:私は削除したファイルを指しているURLのみ。

+0

聖なるもの...私はこの問題を数時間偶然見つけましたが、これはまさにそのケースでした! Visual Controllerは、アプリケーションの完全に別の部分で、viewDidAppearのtmpディレクトリに対してクリーンアップを行い、作成直後にドキュメントピッカーからファイルを完全に削除します。一致、それは追跡するのが難しいです)) – IPv6

+0

私は唯一ではありませんでした!うれしかったよ! – Jesper

1

説明

同様の問題が発生しました。

var documentPicker: UIDocumentPickerViewController = UIDocumentPickerViewController(documentTypes: ["public.data"], in: .import) 

それらがdocumentPickerに選択された後のファイルがapp_id-Inboxディレクトリにコピーされていることを意味します は、私はこのように初期化された文書ピッカーを持っています。デリゲートメソッドdocumentPicker(_:didPickDocumentsAt:)が呼び出されると、app_id-Inboxディレクトリにあるファイルを指し示すURLが与えられます。 (アプリを閉じずに)いくつかの時間後にそれらのURLが存在していないファイルを指した

問題

。その間にtmp/フォルダ内のapp_id-Inboxが消去されたためです。たとえば、ドキュメントを選択してテーブルビューで表示し、その画面にiPhoneを1分間放置すると、から提供されたURLを使用してQLPreviewControllerにファイルを開く特定のドキュメントをクリックしようとすると、ファイルは存在しません。 Appleのドキュメント状態がなく、そのURLを開いていないの分の周りにいた私の場合は、here

UIDocumentPickerModeImport

The URLs refer to a copy of the selected documents. These documents are temporary files. They remain available only until your application terminates. To keep a permanent copy, move these files to a permanent location inside your sandbox.

アプリケーションがを終了するまで、それは明らかに言いますが、以下のため

これはバグのように思えます。

回避策

app_id-Inboxtmp/にフォルダや他のディレクトリから移動したファイルは、新しい場所を指しているURLを使用します。

スウィフト4

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { 
    let newUrls = urls.flatMap { (url: URL) -> URL? in 
     // Create file URL to temporary folder 
     var tempURL = URL(fileURLWithPath: NSTemporaryDirectory()) 
     // Apend filename (name+extension) to URL 
     tempURL.appendPathComponent(url.lastPathComponent) 
     do { 
      // If file with same name exists remove it (replace file with new one) 
      if FileManager.default.fileExists(atPath: tempURL.path) { 
       try FileManager.default.removeItem(atPath: tempURL.path) 
      } 
      // Move file from app_id-Inbox to tmp/filename 
      try FileManager.default.moveItem(atPath: url.path, toPath: tempURL.path) 
      return tempURL 
     } catch { 
      print(error.localizedDescription) 
      return nil 
     } 
    } 
    // ... do something with URLs 
} 

システムは/tmpディレクトリの世話をしますが、それはもはや必要いないときにその内容をクリアすることをお勧めします。

+0

ニース、これは答えを受け入れる必要があります。ありがとうございました。 –

関連する問題