2016-06-16 29 views
0

我越來越想從我的火力地堡儲存下載的圖像時出現以下錯誤:火力地堡貯存:孩子()不與iOS應用工作

錯誤域= 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存儲中手動刪除所述文件夾時出現問題(我通過Firebase門戶網站執行了此操作) - 只是因爲我想驗證一切正常,因此我刪除了文件夾以重新開始 - 期待上面的代碼一旦我再次運行應用程序會重新創建它 - 從那以後,我一次又一次地得到這個錯誤。

真的沒有任何意義。

Firebase存儲是否有任何怪癖或問題?需要解決的某種緩存?

任何提示將不勝感激!

+0

在我看來,'signedInUser.uid'作爲一個對象返回(可能是因爲你沒有強迫它到'String!'?),它指向錯誤的文件。你能證實你得到了正確的「uid」,而且路徑確實正確嗎? –

回答

3

是否有任何怪癖或問題與火力地堡存儲?需要解決的某種 緩存?

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)把下載的代碼的回調上傳代碼裏面。

這樣,直到圖片成功上傳後,下載纔會開始執行。我做了之後,使用火力地堡存儲網頁上運行的應用程序之前刪除的圖像對我的上傳/下載無不利影響,而且這些消息都按預期的順序輸出:

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

2)附上。成功觀察uploadTask。

正如火力地堡文檔描述的,在Monitor Upload Progress section,你可以得到通知,如果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)使用大中央調度通知您當上載是成功的。

您無法控制回調添加到哪些隊列(Firebase方法實現決定),但您可以使用Grand Central Dispatch在任意代碼執行完成時通知您。對我來說,以下工作:

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),並沒有緩解這個問題。我認爲如果上傳回調在後臺線程上執行,那麼在主線程正在休眠時上傳回調將有時間完成,然後在完成睡眠後下載代碼將執行並且下載回調將被添加到隊列中某處,然後下載回調將執行。由於睡眠(10)沒有解決問題,這意味着上傳回調必須已被添加到主線程的執行隊列中,並且睡眠暫停主線程和隊列中的任何內容執行。

這使我相信,上傳和下載的回調被添加到異步隊列主線程(它不是一個同步隊列,否則將回調爲了執行)。我認爲主線程上的一個異步隊列意味着當主線程上有空閒時間時,隊列中的任務將會執行,並且當特定任務中有空閒時間時,您還可以在各種任務之間快速切換,如等待HTTP響應。例如,如果主線程上的異步隊列中有兩個任務,那麼每當任何一個線程中都有空閒時間時,主線程,task1和task2之間會快速切換。