swift4でUserDefaultsを使った1人掲示板を作ってみた。

# __始めに__
swift4で__UserDefaults__を使って、__1人掲示板アプリ__を作ってみました。
対象者は__プログラミング初学者__を対象としています。今回はいまある知識をアウトプットしていこうと思い記事を作成しました。

# __使ったコンポーネント__
1. `UITableView`
2. `UITableViewCell`
3. `UIImageView`
4. `UILabel`
5. `UIButton`
6. (`NSLayoutConstraint`)

#UIStoryBoardの設定

完成版のUIStoryBoardを[GitHub](https://github.com/fummicc1/SelfTimeLine)のREADME.mdに書いたのでそちらをみてくれればと思います。


# __コーディング__
今回は、プロジェクトを作成した段階から開発を始めます。


##掲示板の画面の作成

```swift:TLViewController.swift

import UIKit

class TLViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet var table: UITableView!
    
    var postArray: [String] = [] //全投稿が入った配列
    
    override func viewDidLoad() {
        super.viewDidLoad()
        table.frame = view.frame //テーブルを画面全体に表示
        
        table.delegate = self //デリゲート指定
        table.dataSource = self //データソース指定
    }    
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        readData() //viewWillAppearに書くことで追加後、前の画面に戻ってもすぐに更新がみれます。

    }
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func readData() { //UserDefaultsからデータを取得

        let database = UserDefaults.standard
        
        if let postArray = database.stringArray(forKey: "posts") {
            
            self.postArray = postArray
            
            table.reloadData() //cellの更新
            
        }
        
    }
    
    //セクション毎のセルの個数を返すメソッド
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            return 1
        }else {
            return postArray.count
        }
    }
    
    //cellの情報を決めるところ。
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0 { //最初のセクションは追加ボタンの設定
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
            
            let addPostButton = UIButton(type: UIButtonType.contactAdd)
            
            addPostButton.addTarget(self, action: #selector(addPost), for: UIControlEvents.touchUpInside)
            
            cell?.accessoryView = addPostButton
            
            return cell!
            
        }else {
            
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
            cell?.imageView?.image = UIImage(named: "botti")
            cell?.textLabel?.text = postArray[indexPath.row]
            
            return cell!
        }
    }
    
    //セクションの数を設定するところ
    func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }
    
    //cellをタップした時に呼ばれる。
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("tapped")
    }
    
    @objc func addPost() {
        performSegue(withIdentifier: "toAddPost", sender: nil) //画面遷移をするコード
    }
    
    //ここでは画面遷移の時に遷移先の画面で使いたいデータを送ることができる。
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let addPostViewController = segue.destination as! AddPostViewController //遷移先の画面取得
        addPostViewController.postArray = self.postArray
    }
}
```

## 投稿を追加する画面の作成

```swift:AddPostViewController.swift

import UIKit

class AddPostViewController: UIViewController {

    @IBOutlet var textView: UITextView! //投稿内容を入力するUITextView
    
    var postArray: [String] = [] //全ての投稿を格納した配列
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
    }
    
    @IBAction func back() {
        self.dismiss(animated: true, completion: nil) //画面を戻る。
    }
    
    @IBAction func savePost() {
        
        if let text = textView.text, !text.isEmpty { //textが何か入力されていたら
            
            let database = UserDefaults.standard // データベースを取得
            
            postArray.append(text) //全ての投稿が入った配列に入力した投稿を追加。
            
            database.set(postArray, forKey: "posts") // 投稿をデータベースに保存する
            
            self.dismiss(animated: true, completion: nil) //画面を戻る
            
        }else { //アラートを出して入力不備をユーザーに知らせる。
            let alert = UIAlertController(title: "入力不備", message: "文字を入力してください", preferredStyle: .alert)
            present(alert, animated: true, completion: {
                sleep(1) //アラートの表示時間となる
                alert.dismiss(animated: true, completion: nil) //アラートの削除
            })
        }
    }
    
}

extension UITextView {
    open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.next?.touchesBegan(touches, with: event) // ここを忘れるとタップしても呼ばれません。
        self.resignFirstResponder()
    }
}

```
## UserDefaultsの基本的な使い方。(メモ)

###データベース取得

```swift:TLViewController.swift
let database = Userdefaults.standard
```

###データの読み取り

```swift:TLViewController.swift
if let text = database.string(forKey: "test") { //nilじゃないかの確認!
    label.text = text
}
```

###データの書き込み

```swift:TLViewController.swift
database.set("初投稿", forKey: "posts")
```

#__最後に__

今回記事を書いててめちゃくちゃ大変だと感じましたが、やりながら色々考える機会になったのでこれからも続けていこうと思います！

最後まで読んでいただきありがとうございました。