Help us understand the problem. What is going on with this article?

FirebaseでiOS版簡易SNSを作成する。(タイムライン編 前編)

はじめに

今回、Firebaseを使ってiOS版簡易SNSを作成する記事になっています。
この記事ではタイムライン上でFirestoreに対して書き込みと読み込みを行うまでの部分を行なっています。
また、前回の続きという扱いで進めていきます。

Firestoreを有効にする

  • Firebaseコンソールからプロジェクトを選択し、左のサイドメニューからDatabaseを選択。
  • データベースの作成を選択。

スクリーンショット 2019-08-30 9.01.37.png

  • テストモードで開始します。

スクリーンショット 2019-08-30 9.04.56.png

  • ロケーションはasia-northeast1を選択します。

スクリーンショット 2019-08-30 9.05.28.png

  • これで、Firestoreの設定は完了です。

Main.storyboardを編集

  • 以下のようにテーブルビューをTimelineViewControllerに配置します。

スクリーンショット 2019-08-30 8.11.17.png

  • 投稿を行うためのボタンも配置します。

スクリーンショット 2019-08-30 9.13.02.png

  • AddViewControllerを作成し、Segueで接続する。

demo1

  • 上で繋いだSegueのIdentifierをAddにする。

スクリーンショット 2019-08-30 12.45.52.png

  • AddViewControllerUITextViewUIButtonを配置する。(今回はキーボードと重ならないように上の方に配置しておく。)

スクリーンショット 2019-08-30 12.45.14.png

TimelineViewController.swiftを編集

  • データベースの宣言を行います。
TimelineViewController.swift
import UIKit
import Firebase

class TimelineViewController: UIViewController {

    var me: AppUser!
    var database: Firestore! // 宣言

    override func viewDidLoad() {
        super.viewDidLoad()
        database = Firestore.firestore() // 初期値代入
    }

    // 投稿追加画面に遷移するボタンを押したときの動作を記述。
    @IBAction func toAddViewController() {
    }
}
  • AddViewControllerへ画面遷移を行うコードの記述。
TimelineViewController.swift
@IBAction func toAddViewController() {
    performSegue(withIdentifier: "Add", sender: me)
}
  • 画面遷移時に値を渡すためにprepareメソッドを記述。
TimelineViewController.swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let destination = segue.destination as! AddViewController // segue.destinationで遷移先のViewControllerが取得可能。
    destination.me = sender as! AppUser
}

AddViewControllerを作成、編集。

AddViewController.swift
import UIKit
import Firebase

class AddViewController: UIViewController {

    var me: AppUser!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
  • @IBOUtlet@IBAction関連を記述します。今回は、UITextView@IBOutletで、UIButton@IBActionになります。
import UIKit
import Firebase

class AddViewController: UIViewController {

    @IBOutlet var contentTextView: UITextView! // 追加

    var me: AppUser!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // 追加
    @IBAction func postContent() {        
    }
}
  • UITextViewをカスタマイズ

UITextViewは複数行入力することができるため、returnキーで入力の終了ができません。
なので、キーボードを閉じる処理として別にボタンを用意します。

キーボードを閉じる一連の処理のコード.swift
func setupTextView() {
    let toolBar = UIToolbar() // キーボードの上に置くツールバーの生成
    let flexibleSpaceBarButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) // 今回は、右端にDoneボタンを置きたいので、左に空白を入れる
    let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissKeyboard)) // Doneボタン
    toolBar.items = [flexibleSpaceBarButton, doneButton] // ツールバーにボタンを配置
    toolBar.sizeToFit()
    contentTextView.inputAccessoryView = toolBar // テキストビューにツールバーをセット
}

// キーボードを閉じる処理。
@objc func dismissKeyboard() {
    contentTextView.resignFirstResponder()
}

投稿ボタン (データベースへの書き込み)

投稿ボタンを押したときの処理を記述していきます。

今回は、postsコレクションの中に、投稿を保存していきます。(Firestoreの説明に関してはこちらをご覧ください。)

投稿ボタンを押したときの処理.swift
@IBAction func postContent() {
    let content = contentTextView.text!
    let saveDocument = Firestore.firestore().collection("posts").document()
    saveDocument.setData([
        "content": content,
        "postID": saveDocument.documentID,
        "senderID": user.uid,
        "createdAt": FieldValue.serverTimestamp(),
        "updatedAt": FieldValue.serverTimestamp()
    ]) { error in
        if error == nil {
            self.dismiss(animated: true, completion: nil)
        }
    }
}

Main.storyboardで関連付け

  • クラスをAddViewControllerに設定する。

スクリーンショット 2019-08-30 13.28.44.png

  • 関連付けを行い、実行する。

  • 現在のデモ

demo2

demo3

  • データベース (2回投稿しました。)

スクリーンショット 2019-08-30 13.37.30.png

TimelineViewControllerで投稿を読み込む

  • 投稿を保存する配列の変数の宣言

  • viewWillAppearメソッドの中でデータベースから投稿を読み込む処理を記述していきます。

TimelineViewController.swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    database.collection("posts").getDocuments { (snapshot, error) in
        if error == nil, let snapshot = snapshot {
            self.postArray = []
            for document in snapshot.documents {
                let data = document.data()
                let post = Post(data: data)
                self.postArray.append(post)
            }
            print(self.postArray)
        }
    }
}
  • 出力結果

スクリーンショット 2019-08-31 23.18.52.png

TimelineViewControllerで投稿をテーブルビューに表示する。

  • UIの宣言
// デリゲート・データソースを記述。
class TimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet var tableView: UITableView! // 追加

    override func viewDidLoad() {
        super.viewDidLoad()
        database = Firestore.firestore()
        tableView.delegate = self  // 追加
        tableView.dataSource = self // 追加
    }
}
  • データソースメソッドを追加
class TimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    (省略)

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return postArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        cell.textLabel?.text = postArray[indexPath.row].content
        return cell
    }
}

  • データベースからの取得が完了したらテーブルビューを更新する
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    database.collection("posts").getDocuments { (snapshot, error) in
        if error == nil, let snapshot = snapshot {
            self.postArray = []
            for document in snapshot.documents {
                let data = document.data()
                let post = Post(data: data)
                self.postArray.append(post)
            }
            self.tableView.reloadData() // 先ほど書いたprint文をこちらに変更
        }
    }
}
  • Prototype Cellsを1に変更
    スクリーンショット 2019-08-31 23.41.42.png

  • StoryboardでセルにIdentifierをCellに設定
    スクリーンショット 2019-08-31 23.43.22.png

以上で、関連付けをしてから実行してみてください!

  • デモ

demo

この辺で、タイムライン編の前編を終えて、次回は後編として進めて行きたいと思います。

投稿して、前の画面に戻ると投稿が反映されている。

demo

関連記事

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away