【iOS】プログラミング素人の俺が、Swift + Firebaseを使って、インスタクローンを作る！【写真投稿編】

# **目次**
- 前回
- 写真投稿機能を作る
- 感想
- 参考サイト
- 次回

# **【2018/03/05更新】**
**後述の問題点が解消したので、書き直しました。**

# **前回**
[【iOS】プログラミング素人の俺が、Swift + Firebaseを使って、インスタクローンを作る！①](https://qiita.com/umagoro/items/c6fcdf8cf7eea24a2e0e)

# **写真投稿機能を作る**
今回は写真投稿機能を作るが、少し複雑なので、システムの全体像から入っていく。
### **① 具体的なシステム全体像**

<img width="1185" alt="スクリーンショット 2018-03-05 11.26.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/154610/4957bdc4-6354-068f-bc59-76bdae24c602.png">


手順としては、
1. 画像をStorageにアップロード&ダウンロードURLをRealTime DataBaseに保存
2. ダウンロードURLを取得
3. Storageからダウンロードする 

という感じで。
### **② RealTime Database**
DBの所はまだよくわからない感じだが、とりあえずこのようにした。

<img width="699" alt="スクリーンショット 2018-03-05 20.45.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/154610/b48fa3c1-ff33-7672-38a0-b69a8e70043c.png">

imagesは、まずユーザーUIDで割り振り、その中にダウンロードURLを格納している。
imgcountは、ユーザーの投稿回数を格納している。
この数値を、imagesの画像IDにしている。

### ③ **コード**

```swift:ImageAddViewController.swift
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~~

### ④ **完成品**

![testgif.gif](https://qiita-image-store.s3.amazonaws.com/0/154610/133b0097-90c1-6591-d488-c54150c9e1de.gif)


# **感想**
~~とりあえず、問題点は解消したいですね。~~
それが出来次第、今度は画像をリスト化して、呼び出したいですね。

**【追記】**
問題点、解消しました。
いやぁ〜、大変だった。。。
# **参考サイト**
[[ios]firebase storageを使用して、画像をアップロードしてからRealtime DatabaseにURLを保存するまで](https://qiita.com/goombeer79/items/329680d1cd56190b4f00)
[Firebase Storageに画像をアップロードをするサンプルを作ってみた！](https://qiita.com/nnsnodnb/items/8464369f9c9160f49634)
[FirebaseStorageの画像をSDWebImageで表示しようとして詰まった話](https://qiita.com/k-boy/items/3d6aa6c26a0c6510320e)

# **次回**
[【iOS】プログラミング素人の俺が、Swift + Firebaseを使って、インスタクローンを作る！【画像リスト化編】](https://qiita.com/umagoro/items/a0094fd1eb74ed542077)