[APP開發-使用Swift] 21–2. Firebase — 新增

Chiwen Lai
12 min readNov 9, 2017

--

上一篇文章,我們用Firebase實作好了登入的功能,接下來我們來看看Firebase如何新增資料。如下圖,我們將在「向左滑動」的功能中,加入一個「上傳」的功能,將我們喜愛的餐廳上傳到Firebase資料庫,之後可以分享給其他的App使用者。

  1. 開啟終端機,輸入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 Firebase
struct 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資料庫看看我們的資料是否也出現了呢!

上傳圖片

成功將資料上傳後讓我們獲得了更大的信心,接下來我們來看看如何上傳圖片。

  1. 首先我們必須利用Firegase Storage的功能來儲存我們的圖檔。開啟終端機,輸入open -a Xcode Podfile ,用Xcode編輯Podfile,加入pod 'Firebase/Storage' ,儲存檔案之後,再回到終端機輸入pod install 。如此,我們已將Firebase Storage的Framework加到我們的專案中。

2. 修改RestaurantFIR這個structure,加上image屬性。

import Foundation
import Firebase
struct 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也有一筆資料囉!

>>>21–3. Tab Bar以及UICollectionView

--

--