2016-06-16 15 views
0

Firebaseストレージ:子()のiOSアプリケーションでは動作しません。私は私のFirebaseストレージからイメージをダウンロードしようとすると、次のエラー取得してい

エラードメイン= FIRStorageErrorDomainコード= -13010「オブジェクトを2xxxxxxx8/profile_picは存在しません。

(。私は明らかにプライベート情報をマスクするためにそこまでのxのを置く)

私は、次のコードを使用して、私のFirebase Storageへのパスの参照を追加している:私は、コードを知っている

let storage = FIRStorage.storage() 
let storageRef = storage.referenceForURL("gs://project-4xxxxxxxxxxxxx.appspot.com") 
let profilePicReference = storageRef.child(signedInUser.uid + "/profile_pic") 

をすべてがでした:私のストレージスペースにフォルダが追加され、そのフォルダに画像がアップロードされたことがわかりました。すべてiOSアプリケーションから直接アップロードされました。

Firebase Storageからこのフォルダを手動で削除したときに問題が発生しました。(FirebaseのWebポータルでこれを行いました) - すべてが機能していることを確認したいので、上記のコードを期待してフォルダを削除しました。私は再びアプリケーションを実行した後にそれを作り直すだろう - そしてその後、私は何度もこのエラーを繰り返してきている。

本当に意味がありません。

Firebase Storageには何か不具合や問題はありますか?対処しなければならないキャッシュのいくつかの種類?

ヒントをお聞かせください。

+0

'signedInUser.uid'がオブジェクトとして返されているように見えます(おそらく' String! 'に強制していないからでしょうか?)、間違ったファイルを指しています。あなたは正しい 'uid'を得ていることを確認できますか?パスは本当に正しいですか? –

答えて

3

Firebase Storageには何か不具合や問題はありますか?いくつかの種類の キャッシュを解決する必要がありますか?

UploadTaskは、asynchronouslyを実行します。画像をアップロードした直後に画像をダウンロードしようとすると、エラーを再現できます。起こっているのは、イメージがアップロードを完了する前にダウンロードコードが実行され、イメージに存在しないエラーを生成することです。あなたは、ダウンロードコードがコールバックでいくつかのメッセージをプリントアウトすることにより、あまりにも早く実行されることがわかります。

let storage = FIRStorage.storage() 
    let storageRef = storage.reference() //You don't need to explicitly write the url in your code. 
             //The config file GoogleService-Info.plist will handle that. 

    let imageRef = storageRef.child("images/align_menu.tiff") 

    let localURL = NSBundle.mainBundle().URLForResource(
     "align_menu", 
     withExtension: "tiff" 
    )! 

    //Upload the image: 
    let uploadTask = imageRef.putFile(localURL, metadata: nil) { (metadata, error) -> Void in 
     if let returnedError = error { 
      // Uh-oh, an error occurred! 
      print("[My Upload Error]: \(returnedError)") 
     } else { 
      // Metadata contains file metadata such as size, content-type, and download URL. 
      print("[My Upload Success]:") 
      let downloadURL = metadata!.downloadURL()! 
      print("[URL for download]: \(downloadURL)") 
     } 

    } 

    //Download the image: 
    imageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in 
     if let returnedError = error { 
      // Uh-oh, an error occurred! 
      print("[My Download Error]: \(returnedError)") 
     } 
     else { 
      print("[My Download Success]:") 

      if let validImage = UIImage(data: data!) { 
       NSOperationQueue.mainQueue().addOperationWithBlock() { 
        self.imageView.image = validImage 
       } 
      } 
     } 

    } 

このコードは出力を生成します。

[My Download Error]: ...."Object images/align_menu.tiff does not exist."... 

してから数秒後、私は出力を参照してください。

[My Upload Success]: 
[URL for download]: ... 

これは、アップロードコールバックがアップロードコールバックより前に実行されていることを示しています。私はそれがなぜ起こるのかを詳しく知ることはできませんが、明らかにコールバックはシリアルキューに追加されません。 *

が非同期問題を治すためには、いくつかのオプションがあります。

1)アップロードコードのコールバック内のダウンロードコードを入れてください。

こうして、画像が正常にアップロードされるまでダウンロードは実行されません。私がした後にアプリを実行する前に、FirebaseストレージのWebページを使用して画像を削除する、ということは、私のアップロード/ダウンロードに有害な影響を与えなかった、とのメッセージが予想される順序で出力した:

[My Upload Success]: 
[URL for download]: ... 
[My Download Success]: 

2)取り付け。observerをuploadTaskに渡します。

let storage = FIRStorage.storage() 
    let storageRef = storage.reference() //You don't need to explicitly write the url in your code. 
             //The config file GoogleService-Info.plist will handle that. 

    let imageRef = storageRef.child("images/align_menu.tiff") 

    let localURL = NSBundle.mainBundle().URLForResource(
     "align_menu", 
     withExtension: "tiff" 
    )! 

    //Upload the image: 
    let uploadTask = imageRef.putFile(localURL, metadata: nil) { (metadata, error) -> Void in 
     if let returnedError = error { 
      // Uh-oh, an error occurred! 
      print("[My Upload Error]: \(returnedError)") 
     } else { 
      // Metadata contains file metadata such as size, content-type, and download URL. 
      print("[My Upload Success]:") 
      let downloadURL = metadata!.downloadURL()! 
      print("[URL for download]: \(downloadURL)") 
     } 

    } 


    let observer = uploadTask.observeStatus(.Success) { (snapshot) -> Void in 

     //Download the image: 
     imageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in 
      if let returnedError = error { 
       // Uh-oh, an error occurred! 
       print("[My Download Error]: \(returnedError)") 
      } 
      else { 
       print("[My Download Success]:") 

       if let validImage = UIImage(data: data!) { 
        NSOperationQueue.mainQueue().addOperationWithBlock() { 
         self.imageView.image = validImage 
        } 
       } 
      } 

     } 

    } 

3)使用グランドセントラル派遣は、アップロードを通知する:Monitor Upload Progress sectionに、Firebaseドキュメントで説明したようにuploadTaskが正常に画像をアップロードした場合

は、あなたが通知を受けることができます成功です。

あなたは、コールバックをキューに何を制御できません(Firebaseメソッドの実装があることを決める)に追加されていますが、任意のコードの実行が終了したときに通知するようにグランドセントラル派遣を使用することができます。私にとっては、次の作品:

let storage = FIRStorage.storage() 
    let storageRef = storage.reference() //You don't need to explicitly write the url in your code. 
             //The config file GoogleService-Info.plist will handle that. 

    let imageRef = storageRef.child("images/align_menu.tiff") 

    let localURL = NSBundle.mainBundle().URLForResource(
     "align_menu", 
     withExtension: "tiff" 
    )! 

    let myExecutionGroup = dispatch_group_create() 

    dispatch_group_enter(myExecutionGroup) 
    //Upload the image: 
    let _ = imageRef.putFile(localURL, metadata: nil) { (metadata, error) -> Void in 
     if let returnedError = error { 
      // Uh-oh, an error occurred! 
      print("[My Upload Error]: \(returnedError)") 
     } else { 
      // Metadata contains file metadata such as size, content-type, and download URL. 
      print("[My Upload Success]:") 
      let downloadURL = metadata!.downloadURL()! 
      print("[URL for download]: \(downloadURL)") 

      dispatch_group_leave(myExecutionGroup) 
     } 

    } 

    let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) 

    dispatch_group_notify(myExecutionGroup, queue) { 
     //This callback executes for every dispatch_group_leave(). 

     //Download the image: 
     imageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in 
      if let returnedError = error { 
       // Uh-oh, an error occurred! 
       print("[My Download Error]: \(returnedError)") 
      } 
      else { 
       print("[My Download Success]:") 

       if let validImage = UIImage(data: data!) { 
        NSOperationQueue.mainQueue().addOperationWithBlock() { 
         self.imageView.image = validImage 
        } 
       } 
      } 

     } 

    } 

*は、私は元のアップロードコードとダウンロードコード間のsleep(10)を入れてみました、それが問題を軽減しませんでした。私は、バックグラウンドスレッドでアップロードコールバックが実行されていた場合、メインスレッドがスリープしている間にアップロードコールバックが完了するまでの時間があり、スリープが終了した後にダウンロードコードが実行され、ダウンロードコールバックがキューに追加されるどこかでダウンロードコールバックが実行されます。 sleep(10)は問題を解決しなかったため、メインスレッドの実行キューにアップロードコールバックを追加する必要があり、スリープによってメインスレッドとキュー内のすべてのものが実行されなくなりました。私をリード

は、アップロードとダウンロードのコールバックは、メインスレッド(それ以外のコールバックを順に実行なり、同期キューではありません)に非同期キューに追加されていると信じています。私は、メインスレッドの非同期キューは、メインスレッドにデッドタイムがあると、キュー内のタスクが実行され、デッドタイムがある場合にはさまざまなタスク間で迅速な切り替えが行われることを意味します。 HTTP応答を待っています。たとえば、メインスレッドの非同期キューに2つのタスクがある場合、いずれか1つにデッドタイムがある場合は、メインスレッド、タスク1、およびタスク2の間で迅速な切り替えが行われます。

関連する問題