目次
- 前回
- 写真投稿機能を作る
- 感想
- 参考サイト
- 次回
【2018/03/05更新】
後述の問題点が解消したので、書き直しました。
前回
【iOS】プログラミング素人の俺が、Swift + Firebaseを使って、インスタクローンを作る!①
写真投稿機能を作る
今回は写真投稿機能を作るが、少し複雑なので、システムの全体像から入っていく。
① 具体的なシステム全体像
![スクリーンショット 2018-03-05 11.26.59.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F154610%2F4957bdc4-6354-068f-bc59-76bdae24c602.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=18d44c255fba2977675eaeaa43971a22)
手順としては、
- 画像をStorageにアップロード&ダウンロードURLをRealTime DataBaseに保存
- ダウンロードURLを取得
- Storageからダウンロードする
という感じで。
② RealTime Database
DBの所はまだよくわからない感じだが、とりあえずこのようにした。
![スクリーンショット 2018-03-05 20.45.35.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F154610%2Fb48fa3c1-ff33-7672-38a0-b69a8e70043c.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=fa09e047a31ee7d15dc26737a03ea47c)
imagesは、まずユーザーUIDで割り振り、その中にダウンロードURLを格納している。
imgcountは、ユーザーの投稿回数を格納している。
この数値を、imagesの画像IDにしている。
③ コード
import UIKit
import Firebase
import SDWebImage
//ディスプレイサイズ取得
let w2 = UIScreen.main.bounds.size.width
let h2 = UIScreen.main.bounds.size.height
//カウント設定
var count: String!
//画像表示用ImageView
let imageView = UIImageView(frame: CGRect(x: (w2 - 200) / 2, y: 300, width: 200, height: 200))
class ImageAddViewController: UIViewController {
//DB参照作成
var ref: DatabaseReference!
//ユーザーUID取得
let userID = Auth.auth().currentUser?.uid
//アップロードボタン
let add = UIButton(frame: CGRect(x: (w2 - 150) / 2, y: 150, width: 150, height: 30))
override func viewDidLoad() {
//DBインスタンス作成
ref = Database.database().reference()
super.viewDidLoad()
//アップロードボタン設定
add.backgroundColor = .red
add.addTarget(self, action: #selector(ImageAddViewController.Imageadd(_:)), for: .touchUpInside)
add.setTitle("アップロード", for: UIControlState())
view.addSubview(add)
//ダウンロードURL取得して、Storageからダウンロードする
//ログイン情報取得
let user = Auth.auth().currentUser
if let user = user {
//imgcountのカウントデータ値の存在確認
let imgCount = self.ref.child("imgcount/\(user.uid)/count")
imgCount.observe(DataEventType.value, with: { (snapshot) in
let Count = snapshot.value
var Countstr = Count as? String
if Countstr == nil {
//存在しない場合、新規データ作成(countは0にする)
self.ref.child("imgcount").child(self.userID!).setValue(["count": "0"])
Countstr = "0"
} else {
//データから呼んだ値をカウントアップして、セットする
var CountInt = Int(Countstr!)
CountInt! += 1
let ud = UserDefaults.standard
ud.set(CountInt, forKey: "count")
//ダウンロードURLの存在確認
let imageURL = self.ref.child("images/\(user.uid)/\(Countstr!)/profile")
print(imageURL)
imageURL.observe(DataEventType.value, with: { (snapshot) in
let url = snapshot.value as? String
if url == nil {
print("ファイルなし")
} else {
//ダウンロードURLを取得し、ImageViewに反映
let strURL = URL(string: url!)
imageView.sd_setImage(with: strURL)
self.view.addSubview(imageView)
}
})
}
//imagesのデータの存在確認
let newUser = self.ref.child("images/\(user.uid)/\(Countstr!)/profile")
newUser.observe(DataEventType.value, with: { (snapshot) in
let profile = snapshot.value as? String
if profile == nil {
//データ値がない場合、新規データを作成
self.ref = Database.database().reference()
self.ref.child("images").updateChildValues(["\(self.userID!)": "userID"])
print("新規ユーザー")
} else {
print("既存")
}
})
})
}
}
///アルバム呼び出し
@objc func Imageadd(_ : UIButton) {
pickImageFromLibrary()
}
//カウンタ
func countPhoto() -> String {
let ud = UserDefaults.standard
let count = ud.object(forKey: "count") as! Int
ud.set(count + 1, forKey: "count")
return String(count)
}
}
//アルバムにアクセス
extension ImageAddViewController: UINavigationControllerDelegate {
func pickImageFromLibrary() {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
let controller = UIImagePickerController()
controller.delegate = self
controller.sourceType = UIImagePickerControllerSourceType.photoLibrary
present(controller, animated: true, completion: nil)
}
}
}
//Storageに書き込み
extension ImageAddViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo
info: [String : Any]) {
let storage = Storage.storage()
let storageRef = storage.reference()
let user = Auth.auth().currentUser
if let user = user {
count = countPhoto()
if let data = UIImagePNGRepresentation(info[UIImagePickerControllerOriginalImage] as! UIImage) {
let reference = storageRef.child("image/" + user.uid + "/" + count + ".jpeg")
let meta = StorageMetadata()
meta.contentType = "image/jpeg"
reference.putData(data, metadata: meta, completion: { metaData, error in
if (error != nil) {
print("Uh-oh, an error occurred!")
} else {
//URL型をNSstring型に変更
let downloadURL = metaData!.downloadURL()
let data = downloadURL!.absoluteString
self.ref = Database.database().reference()
self.ref.child("images").child(self.userID!).child(count).updateChildValues(["profile": data])
self.ref.child("imgcount").child(self.userID!).setValue(["count": count])
print("成功!")
}
})
dismiss(animated: true, completion: nil)
}
}
}
}
コードはこんな感じ。
このコードにはまだ問題点があり、
1. ログインする毎に、countが初期化されてしまう(DBも初期値に上書きされてしまう。)
2. 上記の影響で、過去に格納していた画像が上書きされてしまう。
3. 新規ユーザーが最初にログインした場合、画像呼び出しのところで、エラーが起きる。
この問題が解決次第、あげ直しますm(_ _)m
④ 完成品
感想
とりあえず、問題点は解消したいですね。
それが出来次第、今度は画像をリスト化して、呼び出したいですね。
【追記】
問題点、解消しました。
いやぁ〜、大変だった。。。
参考サイト
[ios]firebase storageを使用して、画像をアップロードしてからRealtime DatabaseにURLを保存するまで
Firebase Storageに画像をアップロードをするサンプルを作ってみた!
FirebaseStorageの画像をSDWebImageで表示しようとして詰まった話
次回
【iOS】プログラミング素人の俺が、Swift + Firebaseを使って、インスタクローンを作る!【画像リスト化編】