LoginSignup
0
1

More than 3 years have passed since last update.

[Swift] core dataの基本的な実装をまとめてみた

Posted at

はじめに

core dataについて色々調べ、とりあえず実装できた状態です。
自分なりにまとめてみます。
tableviewcontrollerと、遷移先の項目を追加するview2つを作成します。
core data以外の操作は省略します🙇‍♂️

実装と解説

1 プロジェクト作成

まずはじめにプロジェクトを立ち上げる際に、User Core Dataを選択します。
すると、ファイル名.xcdatamodeldというファイルが追加されます、

2 tableviewcontrollerと追加用のviewcontrollerの実装

イメージはこんな感じです。
スクリーンショット 2021-01-16 21.04.39.png

Core Dataの設定

①のファイルを選択すると、Core Dataの設定ができます。
②でEntityを追加します。
③が追加されます。Entityは今回データを入れておいて保管する場所になります。
今回はメモ内容の保存に使いますので、Memoという名前にしてみます。
Entityは大文字からの名前をつけるのが無難だそうです。
スクリーンショット 2021-01-16 8.04.43.png
④の+を押すと、⑤のAttributeがが追加できます。これは今回追加するデータになります。
今回はメモの内容を保存するnameをstring型、チェックマークの状態を保存するcheckをBoolean型で設定します。
型はTypeから設定できます。
スクリーンショット 2021-01-16 8.16.40.png
各項目のOptionalのチェックを外しておいてください。
ここで一旦ビルドしておきます。しておかないと後々エラーになるそうです。
スクリーンショット 2021-01-16 8.25.35.png

コード

保存の処理

viewContextは変更などを見にいき、操作もできるメソッドで、それを定数contextに入れる
②そのcontextをMemo(context: context)に入れる事で、Core DataであるMemoの変更や操作ができるようになる。
③それを定数memoに入れたので、memo.attributeの項目を操作できる
④最後にsaveContext()でデータを保存して完了!

import UIKit

class AddViewController: UIViewController {

    @IBOutlet weak var addTextField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func addButton(_ sender: Any) {
// persistentContainerは総監督の役割でcore dataに関連するNSManagedObjectContext・
// NS PesistentStoreCoordinator・NSpersistentStoreに指示を出せる。
// 以下のcontextはManagedObjectContextへの参照が含まれている。
// viewContextはNSManagedObjectContext型で、管理されているオブジェクトを操作したり、
// 変更を追跡したりする。
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// (context:)はモデル内の単一のエンティティを表すNSManagedObject(この場合はMemo)のサブクラスに対してのみ、
// 合法的に呼び出すことができる。この場合、Memoの中で変更があるかとかをcontextで追跡し、
// それを呼び出して定数に入れているイメージかな?ManagedObjectのサブクラスを初期化し、
// 指定されたNSManagedObjectContextに挿入できるようになる。
        let memo = Memo(context: context)
//memoはManagedObjectのサブクラスを初期化し、
//指定されたNSManagedObjectContextに挿入できるようになったので、
//以下のように値などを入れる事ができる。
        memo.name = addTextField.text
        memo.check = false
        // 変更があれば保存する処理
        (UIApplication.shared.delegate as! AppDelegate).saveContext()
        navigationController!.popViewController(animated: true)
    }
}

データを取得して、表示するコード

import UIKit

class MemoTableViewController: UITableViewController {

    // 変数memosを用意して、core dataのMemo型を追加していくためにMemo型に指定する
    var memos : [Memo] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: TableViewCell.reuseIdentifier)
    }

    override func viewWillAppear(_ animated: Bool) {
// データを取得する
        getData()
        tableView.reloadData()
    }

    // MARK: - Table view data source

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return memos.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell.reuseIdentifier, for: indexPath) as! TableViewCell

        let memo = memos[indexPath.row]
        cell.configure(isCheck: memo.check, name: memo.name!)

        return cell
    }

    func getData() {
        // 変更箇所を見にいく
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        do {
            // あれば取得
            memos = try context.fetch(Memo.fetchRequest())
        }
        catch {
            print("読み込み失敗")
        }
    }
}

cellの内容

import UIKit

class TableViewCell: UITableViewCell {
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var checkImage: UIImageView!

    static let image = UIImage(named: "check")

    static let reuseIdentifier = "Cell1"

    func configure(isCheck: Bool, name: String) {
// checkマークの表示の処理
        checkImage.image = isCheck ? TableViewCell.image : nil
        label.text = name
    }    
}

データの内容を削除

editingStyle内で処理を書きます。
また同じように、viewContextで操作できるようにします。
context.deleteで削除できます。
あとは削除した状態をsaveContext()で保存してあげれはOKです。

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

        if editingStyle == .delete {
            let memo = memos[indexPath.row]
            context.delete(memo)
            (UIApplication.shared.delegate as! AppDelegate).saveContext()
            do {
                // あれば取得
                memos = try context.fetch(Memo.fetchRequest())
            }
            catch {
                print("読み込み失敗")
            }
        }
        tableView.reloadData()
    }

checkマークの切り替え

!を先頭につける事で値が反転できます。
これをdidSeleceRowAtに書く事で、cellのタップ時に切り替える事ができます。

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let memo = memos[indexPath.row]
        memo.check = !memo.check
        tableView.reloadData()
    }

最後に

まだまだ理解できていないところがありますが、実装段階での理解の手助けになれば幸いです。
間違っている箇所などありましたら遠慮なくご指摘ください。

参考サイト

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1