[APP開發-使用Swift] 21–2. Firebase — 新增
12 min readNov 9, 2017
上一篇文章,我們用Firebase實作好了登入的功能,接下來我們來看看Firebase如何新增資料。如下圖,我們將在「向左滑動」的功能中,加入一個「上傳」的功能,將我們喜愛的餐廳上傳到Firebase資料庫,之後可以分享給其他的App使用者。
- 開啟終端機,輸入
open -a Xcode Podfile
,用Xcode編輯Podfile,加入pod 'Firebase/Database'
,儲存檔案之後,再回到終端機輸入pod install
。如此,我們已將Firebase Database的Framework加到我們的專案中。
2. 宣告我們的資料庫物件var ref: DatabaseReference
, 接著在viewDidLoad()裡加上:
ref = Database.database().reference(withPath: "RestaurantFIR")
3. 在tableView(_:editActionsForRowAt:)
裡面增加以下程式碼,加上上傳的按鈕:
// 上傳
let uploadAction = UITableViewRowAction(style: .default, title: "上傳") { (action, indexPath) in
let restaurant = self.restaurants[indexPath.row]
self.uploadDataToFirebase(values: restaurant)
}
uploadAction.backgroundColor = UIColor.brown
return [uploadAction, shareAction, deleteAction]
4. 新增一個檔案,選擇New File → Swift File,新增RestaurantFIR.swift檔案,宣告RestaurantFIR這個structure。
import Foundation
import Firebasestruct RestaurantFIR {
let key: String
let name: String
let type: String
let location: String
let rating: String?
var isVisited: Bool
let ref: DatabaseReference? init(name: String, type: String, location: String, rating: String?, isVisited: Bool, key: String = "") {
self.key = key
self.name = name
self.type = type
self.location = location
self.rating = rating
self.isVisited = isVisited
self.ref = nil
} init(snapshot: DataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String: AnyObject]
name = snapshotValue["name"] as! String
type = snapshotValue["type"] as! String
location = snapshotValue["location"] as! String
rating = snapshotValue["rating"] as? String
isVisited = snapshotValue["isVisited"] as! Bool
ref = snapshot.ref
} func toAnyObject() -> Any {
return [
"name": name,
"type": type,
"location": location,
"rating": rating,
"isVisited": isVisited
]
}
}
5. 接著實作uploadDataToFirebase這個function:
- 宣告restaurantItem為初始化RestaurantFIR的物件
- 利用
child(_:)
設定key值為小寫的餐廳名稱。 setValue(_:)
將資料存到資料庫,因為這邊接受的是Dictionary型態的資料,因此我們利用toAnyObject()方法做轉型再存入。- 成功的話再利用UIAlertController顯示訊息。
private func uploadDataToFirebase(values: RestaurantMO) { let restaurantItem = RestaurantFIR(name: values.name!, type: values.type!, location: values.location!, rating: values.rating, isVisited: values.isVisited)
let restaurantItemRef = self.ref.child((values.name?.lowercased())!)
restaurantItemRef.setValue(restaurantItem.toAnyObject(), withCompletionBlock: { (error, ref) in
if error == nil {
let alertController = UIAlertController(title: "Success", message: "Upload Successfully", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
})
}
執行看看,向左滑動後按上傳。
顯示上傳成功後,到Firebase資料庫看看我們的資料是否也出現了呢!
上傳圖片
成功將資料上傳後讓我們獲得了更大的信心,接下來我們來看看如何上傳圖片。
- 首先我們必須利用Firegase Storage的功能來儲存我們的圖檔。開啟終端機,輸入
open -a Xcode Podfile
,用Xcode編輯Podfile,加入pod 'Firebase/Storage'
,儲存檔案之後,再回到終端機輸入pod install
。如此,我們已將Firebase Storage的Framework加到我們的專案中。
2. 修改RestaurantFIR這個structure,加上image屬性。
import Foundation
import Firebasestruct RestaurantFIR {
let key: String
let name: String
let type: String
let location: String
let rating: String?
let image: String?
var isVisited: Bool
let ref: DatabaseReference? init(name: String, type: String, location: String, rating: String?, image: String?, isVisited: Bool, key: String = "") {
self.key = key
self.name = name
self.type = type
self.location = location
self.rating = rating
self.image = image
self.isVisited = isVisited
self.ref = nil
} init(snapshot: DataSnapshot) {
key = snapshot.key
let snapshotValue = snapshot.value as! [String: AnyObject]
name = snapshotValue["name"] as! String
type = snapshotValue["type"] as! String
location = snapshotValue["location"] as! String
rating = snapshotValue["rating"] as? String
image = snapshotValue["image"] as? String
isVisited = snapshotValue["isVisited"] as! Bool
ref = snapshot.ref
} func toAnyObject() -> Any {
return [
"name": name,
"type": type,
"location": location,
"rating": rating,
"image": image,
"isVisited": isVisited
]
}
}
3. 接下來修改uploadDataToFirebase,加上參數imageUrl,以便存放我們圖檔的網址及檔名。
private func uploadDataToFirebase(values: RestaurantMO, imageUrl: String) { let restaurantItem = RestaurantFIR(name: values.name!, type: values.type!, location: values.location!, rating: values.rating, image: imageUrl, isVisited: values.isVisited)
let restaurantItemRef = self.ref.child((values.name?.lowercased())!)
restaurantItemRef.setValue(restaurantItem.toAnyObject(), withCompletionBlock: { (error, ref) in
if error == nil {
let alertController = UIAlertController(title: "Success", message: "Upload Successfully", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
})
}
4. 在uploadAction中,我們利用Firebase Storage功能上傳我們的餐廳圖片。
- 利用
putData(_:, metadata:)
將圖檔上傳。 - 再將metadata.downloadURL裡的檔案網址存到我們的image欄位中。
// 上傳
let uploadAction = UITableViewRowAction(style: .default, title: "上傳") { (action, indexPath) in
let restaurant = self.restaurants[indexPath.row]
let imageName = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("\(imageName).png") if let imageToStorage = UIImage(data: restaurant.image as! Data) {
if let uploadData = UIImagePNGRepresentation(imageToStorage) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata,error) in
if error != nil {
print(error)
}
if let imageUrl = metadata?.downloadURL()?.absoluteString {
self.uploadDataToFirebase(values: restaurant, imageUrl: imageUrl)
}
})
}
}
}
5. 執行看看,同一筆再上傳一次,同樣的Key,Firebase會覆蓋過去。
image欄位有值,查詢Storage也有一筆資料囉!