見出し画像

【徒然DB】気ままにUIKit-CoreData編3〜カスタムクラス〜

概要

このマガジンは四十を過ぎたおっさんが、

を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。

今回

をハイ、レッツゴ🕺

前準備

念の為、

  1. バックアップ

  2. 新規クラスを追加

  3. メニュービューと新規ビューを追加

  4. 今回用の事前準備

をやってから本題へ💃

ま、前々回のコードを使って一旦こんな感じかな💦

今回のコード(事前準備)

class CustomClassCoreDataViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var myTextField: UITextField!
    @IBOutlet weak var myLabel: UILabel!
    //管理オブジェクトコンテキスト
    var managedContext:NSManagedObjectContext!
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        do {
            //管理オブジェクトコンテキストを取得する。
            let applicationDelegate = UIApplication.shared.delegate as! AppDelegate
            managedContext = applicationDelegate.persistentContainer.viewContext
            //管理オブジェクトコンテキストからPlayerエンティティを取得する。
            let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
            let result = try managedContext.fetch(fetchRequest) as! [NSManagedObject]
            //すべてのPlayerエンティティの名前をラベルに表示する。
            for data in result {
                myLabel.text = myLabel.text! + "," + String(describing: data.value(forKey:"name")!)
            }
            //デリゲート先に自分を設定する。
            myTextField.delegate = self
        } catch {
            print(error)
        }
    }
    //Returnキー押下時の呼び出しメソッド
    func textFieldShouldReturn(_ textField:UITextField) -> Bool {
        do {
            //ラベルの値にテキストフィールドの値を追記する。
            myLabel.text = myLabel.text! + "," + myTextField.text!
            //新しいPlayerエンティティを管理オブジェクトコンテキストに格納する。
            let player = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedContext)
            //Playerエンティティの名前にテキストフィールドの値を設定する。
            player.setValue(myTextField.text, forKey:"name")
            //管理オブジェクトコンテキストの中身を永続化する。
            try managedContext.save()
            //キーボードをしまう
            self.view.endEditing(true)
        } catch {
            print(error)
        }
        return true
    }
}

本題

今回は、

ここの部分みたいね👀

Class:カスタムクラスを使う大きな利点は属性値へのアクセスが簡潔に記述できる

Module:モジュールとは、プロジェクトをビルドしたものやフレームワーク。
👉現在のプロジェクトの中にカスタムクラスを作る場合は「Current Product Module」に設定

サイト記事当時から、Codegenって項目が増えてるね、、、

メニューは3つですな🤔

てことらしい。

さて、記事の内容に戻って、

//カスタムクラスを使ってないときの属性値へのアクセス
player.setValue(testTextField.text, forKey:"name")

↓ カスタムクラスを使うと、、、

//カスタムクラスを使っているときの属性値のアクセス
player.name = testTextField.text

てことらしい👀

結合しながら行ってるからここが上手く出来るのか?
これまでに作った2つのビューに影響がないのか?

ってところが既に不安ではあるけど、失敗なら失敗で
何かの参考にはなるからね〜〜〜🕺

⒈メニュー⇒「Editor」⇒「Create NSManagedObject Subclass」

左側のデータモデルを選んで〜〜〜
コイツを選択〜〜〜
チェック入ってるね👀
今回はPlayerにだけチェックを入れて〜〜〜
このプロジェクトがちゃんとターゲットになってるのを確認して
Create〜〜〜〜
が出来上がるんだけど、既にサイト記事とは違う様子、、、

しかも、、、

どちらもエラーが、
発生してるね👀

を見ると、、、(ちょっと古いけど)どうやら、

Codegenを「Manual/None」に変更します。(Class Definitionだとエラーが出ました。)

ってことなので〜〜〜

該当するEntityのCodegenをコイツに変更して〜〜〜
やり直すとエラーは発生しなくなった〜〜〜

冒頭で、

Codegenってなんぞ👀

って感じで違和感があったのが早速勘が当たったね🕺

⒉作られたクラスのコードを見ると、、、

NSManagedObjectクラスを継承したPlayerクラス

@objc(Player)
public class Player: NSManagedObject {

}

Playerクラスを拡張したクラス

extension Player {
    @nonobjc public class func fetchRequest() -> NSFetchRequest<Player> {
        return NSFetchRequest<Player>(entityName: "Player")
    }
    @NSManaged public var age: Int16
    @NSManaged public var name: String?
}
extension Player : Identifiable {

}

て違いみたいだね👀

⒊コードをEntityに適用

サイト記事のとおりに、、、

てな感じで設定して〜〜〜〜

⒋コード組み込み

//
//  ViewController.swift
//
import UIKit
import CoreData
class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var testLabel: UILabel!
    @IBOutlet weak var testTextField: UITextField!
    //管理オブジェクトコンテキスト
    var managedContext:NSManagedObjectContext!
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        do {
            //管理オブジェクトコンテキストを取得する。
            let applicationDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
            managedContext = applicationDelegate.managedObjectContext
            //管理オブジェクトコンテキストからPlayerエンティティを取得する。
            let fetchRequest = NSFetchRequest(entityName: "Player")
            let result = try managedContext.executeFetchRequest(fetchRequest) as! [Player]
            //すべてのPlayerエンティティの名前をラベルに表示する。
            for data in result {
                testLabel.text = testLabel.text! + "," + data.name!
            }
            //デリゲート先に自分を設定する。
            testTextField.delegate = self
        } catch {
            print(error)
        }
    }
    //Returnキー押下時の呼び出しメソッド
    func textFieldShouldReturn(textField:UITextField) -> Bool {
        do {
            //ラベルの値にテキストフィールドの値を追記する。
            testLabel.text = testLabel.text! + "," + testTextField.text!
            //新しいPlayerエンティティを管理オブジェクトコンテキストに格納する。
            let player = NSEntityDescription.insertNewObjectForEntityForName("Player", inManagedObjectContext: managedContext) as! Player
            //Playerエンティティの名前にテキストフィールドの値を設定する。
            player.name = testTextField.text
            //管理オブジェクトコンテキストの中身を永続化する。
            try managedContext.save()
            //キーボードをしまう
            self.view.endEditing(true)
        } catch {
            print(error)
        }
        return true
    }
}

を参考に、コード書き換え

今回のコード(まとめ)

class CustomClassCoreDataViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var myTextField: UITextField!
    @IBOutlet weak var myLabel: UILabel!
    //管理オブジェクトコンテキスト
    var managedContext:NSManagedObjectContext!
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        do {
            //管理オブジェクトコンテキストを取得する。
            let applicationDelegate = UIApplication.shared.delegate as! AppDelegate
            managedContext = applicationDelegate.persistentContainer.viewContext
            //管理オブジェクトコンテキストからPlayerエンティティを取得する。
            let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
            let result = try managedContext.fetch(fetchRequest) as! [Player]
            //すべてのPlayerエンティティの名前をラベルに表示する。
            for data in result {
                myLabel.text = myLabel.text! + "," + data.name!
            }
            //デリゲート先に自分を設定する。
            myTextField.delegate = self
        } catch {
            print(error)
        }
    }
    //Returnキー押下時の呼び出しメソッド
    func textFieldShouldReturn(_ textField:UITextField) -> Bool {
        do {
            //ラベルの値にテキストフィールドの値を追記する。
            myLabel.text = myLabel.text! + "," + myTextField.text!
            //新しいPlayerエンティティを管理オブジェクトコンテキストに格納する。
            let player = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedContext) as! Player
            //Playerエンティティの名前にテキストフィールドの値を設定する。
            player.name = myTextField.text
            //管理オブジェクトコンテキストの中身を永続化する。
            try managedContext.save()
            //キーボードをしまう
            self.view.endEditing(true)
        } catch {
            print(error)
        }
        return true
    }
}

⒌シミュレータで実行

白石さんを入力して〜〜〜
でけたーーー🕺
前々回やったヤツにも反映されていて、
河野を入力して〜〜〜
DBに追加されたのを確認👀
今回のビューにも反映できてるので、問題なし🕺
実機もバッチシを確認済み〜〜〜〜

ブラッシュアップ

地球儀ボタンを追加

てな感じで〜〜〜

記事公開後、

ハイ、完了💃
実機も問題なし🕺

Apple公式

さてと、次回は

をレッツゴする🕺

この記事が気に入ったらサポートをしてみませんか?