RealmとTableViewのシンプルアプリ

#RealmとTableViewのシンプルアプリ 

<img width="150" alt="A0C206FD-8D03-4457-84EC-F3DFD6DC49E7_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/621f9298-56b9-8788-89ad-a4c208d5bd05.jpeg"> <img width="143" alt="C40F97E9-176D-40BB-91D6-0A722F817DC4_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/eb90a240-b4e8-f8e4-cfcb-e000e0e25e6c.jpeg"> <img width="146" alt="31C4512E-5D31-4520-88F3-0118A411810B_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/7804a2bc-e3b3-910d-1a2b-dc69b27072c8.jpeg"> <img width="140" alt="79A4FF00-8C55-43B6-8AC8-1FD17341C3C6_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/3dfbb61e-cfae-81f8-2019-6c6a3b6aee9d.jpeg">
こんな感じのシンプルなアプリです。  

#機能説明
 * textFieldに文字を入力、追加ボタン　➡️ Realmに保存 ➡️ tableViewに反映　
 * Realmに保存済みデータの変更、削除　
 * cellをタップでtextField入りのアラートを表示
 * tableViewのcellを横にスライドさせるとdeleteが表示される
   
#コードと簡単に解説
 
* Podfileには、pod 'RealmSwift'を入力

```言語:Podfile
 pod 'RealmSwift'
```

## Model

* Realmに保存んする為のクラスの作成

```Swift:RealmDatas
import Foundation
import RealmSwift

class RealmDatas:Object{
    
    @objc dynamic var japanese = String()
    @objc dynamic var english = String()
    
}
```

* RealmCRUDModelに追加、取得、更新、削除機能を`extension`を用いて入力する

```Swift:RealmCRUDModel
import Foundation
import RealmSwift

class RealmCRUDModel{
    
    var readResultRealmArray:[[String:String]] = []  //取得した値を入れる配列
    
}
```

* RealmにtextFieldから受け取った値を保存する為のメソッド
* 引数に`textField.text`から受け取った値を入れます

```Swift:RealmCRUDModel
extension RealmCRUDModel{ //Realmに保存
    
    func createRealm(createJp:String,createEng:String){
        
        do{
            let realm = try Realm() 
            let realmDatas = RealmDatas()
            
            realmDatas.japanese = createJp
            realmDatas.english = createEng
            
            try realm.write({
                
                realm.add(realmDatas)
                
            })
        }catch{
            
            print(error.localizedDescription)
            
        }
    }
}
```
* Realmに保存済みのデータを取得するメソッド

```Swift:RealmCRUDModel
extension RealmCRUDModel{ //Realmのデータを取得
    
    func readRealm(){
        
        do{
            let realm = try Realm()
            self.readResultRealmArray = [] //取得済みの値を一度空にする
            
            for resultData in realm.objects(RealmDatas.self){
                
                self.readResultRealmArray.append(["RealmJp":resultData.japanese,"RealmEng":resultData.english])
                
            }            
        }catch{
            
            print(error.localizedDescription)
            
        }
    }
}
```
* Realmに保存済みのデータを更新するメソッド
* 引数にアラートの`textField.text`から値を受け取ります
* `selectCell`は`didSelectRowAt`で`index.row`を受け取ります   
 
```Swift:RealmCRUDModel
extension RealmCRUDModel{  //Realmのデータを更新
    
    func updateRealm(updateJp:String,updateEng:String,selectCell:Int){
        
        do{
            let realm = try Realm()
            let readRealm = realm.objects(RealmDatas.self)
            
            try realm.write({
                
                if (updateJp.isEmpty && updateEng.isEmpty) != true{
                    
                    readRealm[selectCell].japanese = updateJp
                    readRealm[selectCell].english = updateEng
                    self.readRealm()  //データに変更が加わったので、取得をやり直す
                
                }else if updateJp.isEmpty != true && updateEng.isEmpty == true{
                    
                    readRealm[selectCell].japanese = updateJp
                    self.readRealm()  //データに変更が加わったので、取得をやり直す
                    
                }else{
                    
                    readRealm[selectCell].english = updateEng
                    self.readRealm()  //データに変更が加わったので、取得をやり直す
                    
                }
            })            
        }catch{
            
            print(error.localizedDescription)
            
        }
    }
}
```
* Realmに保存済みのデータを全て削除します
*  Realmのデータを削除したので、`readResultRealmArray`内のデータも削除します。存在しないデータが`tableView`に表示されるのを防ぎます。


```Swift:RealmCRUDModel
extension RealmCRUDModel{  //Realmのデータを全て削除
    
    func allDeleteRealm(){
        
        do{
            let realm = try Realm()
            
            try realm.write({
                
                realm.delete(realm.objects(RealmDatas.self))
                self.readResultRealmArray = [] 
                
            })            
        }catch{
            
            print(error.localizedDescription)
            
        }
    }
}
```

* `selectCell`には`index.row`が入る事になります
* 削除したデータと同じ`index.row`の`readResultRealmArray`の値も削除します。存在しないデータが`tableView`に表示されるのを防ぎます。

```Swift:RealmCRUDModel
extension RealmCRUDModel{  //Realmの選択したデータを削除
    
    func selectDeleteRealm(selectCell:Int){
        
        do{
            let realm = try Realm()
            
            try realm.write({
                
                realm.delete(realm.objects(RealmDatas.self)[selectCell])
                self.readResultRealmArray.remove(at: selectCell)
                
            })
            
        }catch{
            
            print(error.localizedDescription)
            
        }
    }
}


```
## View

* tableViewのcellをタップした時に、アラートを表示
* アラートの中に`textField`を追加しています。
* 変更をタップするとModelで作った`updateRealm`を使用する

```Swift:Alert
import Foundation
import UIKit


extension ViewController{
    
    func createTextFieldAlert(deleteCellNumber:Int){

       var jpTextField:UITextField?
       var engTextField:UITextField?

       let alert = UIAlertController(title: "変更確認アラート", message:"変更する場合は、値を入力して下さい", preferredStyle: .alert)

       alert.addTextField { (alertJpTextField:UITextField) in

            alertJpTextField.placeholder = "日本語"
            jpTextField = alertJpTextField

       }

       alert.addTextField { (alertEngTextField:UITextField) in

            alertEngTextField.placeholder = "英語"
             engTextField = alertEngTextField

       }

       alert.addAction(UIAlertAction(title: "キャンセル", style: .default, handler: nil))
       
       alert.addAction(UIAlertAction(title: "変更", style: .default, handler: { _ in

            self.realmCRUDModel.updateRealm(updateJp: (jpTextField?.text)!, updateEng: (engTextField?.text)!, selectCell: deleteCellNumber)

            self.realmCRUDModel.readRealm()
            print("成功")
            self.tableView.reloadData()

        }))

        present(alert, animated: true, completion: nil)

   }  
}
```

## Controller

```Swift:ViewController
import UIKit
import ViewAnimator

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    

    @IBOutlet weak var japaneseTextField: UITextField!
    @IBOutlet weak var englishTextField: UITextField!
    @IBOutlet weak var addButton: UIButton!
    @IBOutlet weak var tableView: UITableView!
    
    
    let realmCRUDModel = RealmCRUDModel()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.tableView.delegate = self
        self.tableView.dataSource = self
        
        self.realmCRUDModel.readRealm()
        
    }
    
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        self.addButton.layer.cornerRadius = 17.0
        
        tableView.reloadData()
        
    }
    
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        
        return 65
        
    }
    
    
    func numberOfSections(in tableView: UITableView) -> Int {
        
        return 1
        
    }
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return realmCRUDModel.readResultRealmArray.count
        
    }
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        
        let cellJapaneseLabel = cell.contentView.viewWithTag(1) as! UILabel
        let cellEnglishLabel = cell.contentView.viewWithTag(2) as! UILabel
        
        cellJapaneseLabel.text = self.realmCRUDModel.readResultRealmArray[indexPath.row]["RealmJp"]
        cellEnglishLabel.text = self.realmCRUDModel.readResultRealmArray[indexPath.row]["RealmEng"]
        
        return cell
        
    }
    
    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        
        if editingStyle == UITableViewCell.EditingStyle.delete {
            
            self.realmCRUDModel.selectDeleteRealm(selectCell: indexPath.row)
            self.tableView.deleteRows(at: [indexPath as IndexPath], with: .automatic)
            self.tableView.reloadData()
            
        }
        
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        self.createTextFieldAlert(deleteCellNumber: indexPath.row)
        
    }
    
    
//追加ボタン処理
    @IBAction func add(_ sender: Any) {
        
        self.realmCRUDModel.createRealm(createJp: japaneseTextField.text!, createEng: englishTextField.text!)
        
        self.japaneseTextField.text = ""
        self.englishTextField.text = ""
    
        self.realmCRUDModel.readRealm()
        self.tableView.reloadData()
        
    }
    
    
//Realmに保存してあるデータを全て削除
    @IBAction func allDelete(_ sender: Any) {
        
        self.realmCRUDModel.allDeleteRealm()
        self.tableView.reloadData()
        
    }
    
}
```

#終わり
かなり簡単にしか解説していないので、質問はコメントまでお願いします。
間違ってるコードや「こんな書き方もあるよー」など指摘して頂けると嬉しいです