2015-11-11 53 views
4

我試圖從Firebase中讀取/顯示圖片。我首先編碼圖像,然後將此編碼的字符串發佈到Firebase。這運行良好。當我嘗試解碼來自Firebase的編碼字符串並將其轉換爲圖像時,我得到一個零值異常。Swift2從Firebase中檢索圖片

這就是我現在的儲蓄圖像以火力

var base64String: NSString! 
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) { 

    self.dismissViewControllerAnimated(true, completion: nil) 

    imageToPost.image = image 

    var uploadImage = image as! UIImage 
    var imageData = UIImagePNGRepresentation(uploadImage)! 
    self.base64String = imageData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength) 
    let ref = Firebase(url: "https://XXX.firebaseio.com") 

    var quoteString = ["string": self.base64String] 
    var usersRef = ref.childByAppendingPath("goalImages") 
    var users = ["image": quoteString] 
    usersRef.setValue(users) 

    displayAlert("Image Posted", message: "Your image has been successfully posted!") 
} 

這是我想讀從火力地堡

// ViewController.swift 

import UIKit 
import Firebase 

class ViewController: UIViewController { 
@IBOutlet weak var image: UIImageView! 
var base64String: NSString! 

@IBAction func buttonClicked(sender: AnyObject) { 

    sender.setTitle("\(sender.tag)", forState: UIControlState.Normal) 

} 

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 

    let ref = Firebase(url: "https://XXX.firebaseio.com/goalImages/image/string") 

    ref.observeEventType(.Value, withBlock: { snapshot in 

     self.base64String = snapshot.value as! NSString 
     let decodedData = NSData(base64EncodedString: self.base64String as String, options: NSDataBase64DecodingOptions()) 
     //Next line is giving the error 
     var decodedImage = UIImage(data: decodedData!) 

     self.image.image = decodedImage 
     }, withCancelBlock: { error in 
      print(error.description) 
     }) 

} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 
} 

錯誤的圖像說:「致命錯誤:意外發現零,同時展開一個可選值「; encodedData是零。有人可以解釋發生了什麼問題嗎?

+1

嘗試NSDataBase64DecodingOptions.IgnoreUnknownCharacters – Jay

+0

我有同樣的問題,我固定它利用@jay評論。您應該寫一個答案,以便提問的用戶可以將其標記爲解決方案。唯一存在的問題是解碼後的圖像旋轉90度,從水平到垂直。我能解決這個問題嗎? – eeschimosu

+0

@eschimosu完成 - 轉換爲答案。就旋轉而言......它不應該是代碼本身中的東西造成的。我作爲一個用例添加了一些代碼給我的答案。 – Jay

回答

6

而不是

let decodedData = NSData(base64EncodedString: self.base64String as String, 
            options: NSDataBase64DecodingOptions()) 

嘗試添加IgnoreUnknownCharacters

NSDataBase64DecodingOptions.IgnoreUnknownCharacters 

使用示例:編碼JPG,商店和火力

編碼讀取和寫入我們最喜歡的星船

if let image = NSImage(named:"Enterprise.jpeg") { 
    let imageData = image.TIFFRepresentation 
    let base64String = imageData!.base64EncodedStringWithOptions(.Encoding64CharacterLineLength) 
    let imageRef = myRootRef.childByAppendingPath("image_path") 
    imageRef.setValue(base64String) 

讀取和解碼

 imageRef.observeEventType(.Value, withBlock: { snapshot in 

      let base64EncodedString = snapshot.value 
      let imageData = NSData(base64EncodedString: base64EncodedString as! String, 
          options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters) 
      let decodedImage = NSImage(data:imageData!) 
      self.myImageView.image = decodedImage 

      }, withCancelBlock: { error in 
       print(error.description) 
     }) 
+0

這工作完美。唯一的問題是編碼和解碼需要花費很多時間並凍結應用程序。 – eeschimosu

+0

Firebase使用異步調用,因此它不應該在寫入或讀取數據期間凍結應用程序。這就是說,在我的示例代碼中,imageRef.setValue應該可以在一個塊中完成,這樣您就可以知道它何時完成了寫週期。另一方面,讀取和解碼已經在一個塊中,因此它應該只能從Firebase返回數據一樣快地解碼。如果編碼結構合理,只有編碼/解碼完成後才能解決問題。也許有一些示例代碼的另一個問題是爲了? – Jay

5

火力地堡的工程師在這裏:

我強烈建議使用新的API Firebase Storage上傳圖像火力地堡。它使用簡單,成本低,並且由大規模的Google Cloud Storage支持。

您可以從NSData上傳或NSURL指向本地文件(我會告訴NSData,但原理是一樣的):

// Data in memory 
let data: NSData = ... 

// Create a reference to the file you want to upload 
let riversRef = storageRef.child("images/rivers.jpg") 

// Upload the file to the path "images/rivers.jpg" 
let uploadTask = riversRef.putData(data, metadata: nil) { metadata, error in 
    if (error != nil) { 
    // Uh-oh, an error occurred! 
    } else { 
    // Metadata contains file metadata such as size, content-type, and download URL. 
    let downloadURL = metadata!.downloadURL 
    // This can be stored in the Firebase Realtime Database 
    // It can also be used by image loading libraries like SDWebImage 
    } 
} 

你甚至可以暫停和恢復上傳,你可以輕鬆地監控上傳進步:

// Upload data 
let uploadTask = storageRef.putData(...) 

// Add a progress observer to an upload task 
uploadTask.observeStatus(.Progress) { snapshot in 
    // Upload reported progress 
    if let progress = snapshot.progress { 
    let percentComplete = 100.0 * Double(progress.completedUnitCount)/Double(progress.totalUnitCount) 
    } 
} 
+1

嗨,邁克。我目前正在使用Firebase。如何從我的項目Firebase存儲分區抓取圖像並將其顯示在UIImageView中?請注意,我通過Firebase控制檯手動上傳了所有圖片。謝謝! – brkr

+2

@brkr,您將創建一個引用(在控制檯的文件查看器中,當您單擊圖像時,您會在側面板中看到一個URL,它有一個gs:// bucket/path/to /你的/圖片URL),然後你可以使用它來下載數據。查看下載文檔以獲取更多信息:https://firebase.google.com/docs/storage/ios/download-files –

+0

太棒了!您認爲保存用戶端圖像的最佳方式是什麼?我用200種不同類型的槍/槍皮製作遊戲。對於新用戶,所有槍支都將被鎖定爲默認佔位符。但是當他們解鎖他們時,我需要更新顯示的圖像和數據。我應該保存到內存還是本地?圖像很小,每個70KB。 – brkr