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