【徒然DB】気ままにUIKit-CoreData編5〜外部ファイルに保存されない一時的な属性を定義〜
概要
このマガジンは四十を過ぎたおっさんが、
を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。
今回
をハイ、レッツゴ🕺
前準備
念の為、
バックアップ
新規クラスを追加
メニュービューと新規ビューを追加
今回用の事前準備
をやってから本題へ💃
ここで〜〜〜
テストプロジェクトの方は、前回使わんなあ〜〜
って言っていた、Constraintsをnameでやってしまっていて、
かなりな影響度が他のビューにまで及んで、
なんかでデータモデルのバージョンを管理しないとCoreDataと連携してる全てのビューが、Playerエンティティ内のnameデータがまっさらでない限り、開けなくなる様子
👉影響度合いがデカ過ぎて、このプロジェクトの趣旨に反しまくってくるので。
//
// Player+CoreDataProperties.swift
//
import Foundation
import CoreData
extension Player {
@NSManaged var name: String?
@NSManaged var age: NSNumber?
@NSManaged var adult: NSNumber?
}
//
// ViewController.swift
//
import UIKit
import CoreData
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var testLabel: UILabel!
@IBOutlet weak var testTextField1: UITextField!
@IBOutlet weak var testTextField2: UITextField!
//管理オブジェクトコンテキスト
var managedContext:NSManagedObjectContext!
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//管理オブジェクトコンテキストを取得する。
let applicationDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
managedContext = applicationDelegate.managedObjectContext
//managedContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
//保存データを表示する。
displayData()
//デリゲート先に自分を設定する。
testTextField1.delegate = self
testTextField2.delegate = self
}
//保存データ表示メソッド
func displayData(){
do {
//Playエンティティで保存されているデータを取得する。
let fetchRequest = NSFetchRequest(entityName: "Player")
let result = try managedContext.executeFetchRequest(fetchRequest) as! [Player]
//取得したデータをラベルに表示する。
var outputStr = ""
for data in result {
if let name = data.name, age = data.age {
outputStr = outputStr + "," + name + "," + String(age)
}
}
testLabel.text = outputStr
} catch {
print(error)
}
}
//Returnキー押下時の呼び出しメソッド
func textFieldShouldReturn(textField:UITextField) -> Bool {
//キーボードをしまう
self.view.endEditing(true)
return true
}
//ボタン押下時の呼び出しメソッド
@IBAction func pushButton(sender: UIButton) {
do {
//nameの値が同じオブジェクトを検索する。
let fetchRequest = NSFetchRequest(entityName: "Player")
fetchRequest.predicate = NSPredicate(format: "name = %@", testTextField1.text!)
let players = try managedContext.executeFetchRequest(fetchRequest) as! [Player]
if (players.count == 0) {
//検索にヒットしなかった場合は新しいオブジェクトを管理オブジェクトコンテキストに格納する。
let player = NSEntityDescription.insertNewObjectForEntityForName("Player", inManagedObjectContext: managedContext) as! Player
player.name = testTextField1.text!
player.age = Int(testTextField2.text!)
} else if(players.count == 1) {
//検索にヒットした場合は、そのオブジェクトを更新する。
players.first!.age = Int(testTextField2.text!)
} else {
print("想定外")
}
//管理オブジェクトコンテキストに格納したデータを保存する。
try managedContext.save()
//データを表示する。
displayData()
} catch {
print(error)
}
}
}
てコードは、
extension Player {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Player> {
return NSFetchRequest<Player>(entityName: "Player")
}
@NSManaged public var age: Int16
@NSManaged public var name: String?
@NSManaged var adult: NSNumber?
}
extension Player : Identifiable {
}
class TemporaryAttributeCoreDataViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myAgeTextField: UITextField!
@IBOutlet weak var myNameTextField: UITextField!
//管理オブジェクトコンテキスト
var managedContext:NSManagedObjectContext!
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//管理オブジェクトコンテキストを取得する。
let applicationDelegate = UIApplication.shared.delegate as! AppDelegate
managedContext = applicationDelegate.persistentContainer.viewContext
//保存データを表示する。
displayData()
//デリゲート先に自分を設定する。
myNameTextField.delegate = self
myAgeTextField.delegate = self
}
//保存データ表示メソッド
func displayData(){
do {
//Playエンティティで保存されているデータを取得する。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
let result = try managedContext.fetch(fetchRequest) as! [Player]
//取得したデータをラベルに表示する。
var outputStr = ""
for data in result {
myLabel.text = outputStr + "," + data.name! + "," + String(describing: data.age)
}
} catch {
print(error)
}
}
//Returnキー押下時の呼び出しメソッド
func textFieldShouldReturn(_ textField:UITextField) -> Bool {
//キーボードをしまう
self.view.endEditing(true)
return true
}
//ボタン押下時の呼び出しメソッド
@IBAction func myPush(_ sender: UIButton) {
do {
//nameの値が同じオブジェクトを検索する。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
//検索にヒットしなかった場合は新しいオブジェクトを管理オブジェクトコンテキストに格納する。
let player = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedContext) as! Player
player.name = myNameTextField.text!
player.age = Int16(myAgeTextField.text!)!
//管理オブジェクトコンテキストに格納したデータを保存する。
try managedContext.save()
//データを表示する。
displayData()
} catch {
print(error)
}
}
}
てな感じで、nameを一意制約を付けてない
👇
fetchRequest.predicate = NSPredicate(format: "name = %@", testTextField1.text!)
let players = try managedContext.executeFetchRequest(fetchRequest) as! [Player]
if (players.count == 0) {
} else if(players.count == 1) {
//検索にヒットした場合は、そのオブジェクトを更新する。
players.first!.age = Int(testTextField2.text!)
} else {
print("想定外")
}
の部分は大幅に削除したり、
for data in result {
if let name = data.name, age = data.age {
outputStr = outputStr + "," + name + "," + String(age)
}
}
も特に無条件でラベルに表示できるように変更した〜〜〜💦
てな感じで、ここまで書けばわかると思うけど、
サイト記事のサンプルプロジェクトとはかけ離れて、
既にかなりややこしいことになっている
内容を見た感じ。
ただ単に、
テストって値を一時エンティティを作って、
プロパティに追加すればいいだけ〜〜〜
って感じなので、
後はサイト記事の重要項目などを追って簡単に済ませることにしまする〜〜〜
本題
Name:属性の名前。
Transient:チェックを入れると、外部ファイルに保存されない一時的な属性になる。
てことね👀
⒈Attributeにtestを追加して、Tranisientにチェックを入れる
⒉Player+CoreDataProperties.swiftファイルに、プロパティを追加
⒊コード組み込み
class TemporaryAttributeCoreDataViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myAgeTextField: UITextField!
@IBOutlet weak var myNameTextField: UITextField!
//管理オブジェクトコンテキスト
var managedContext:NSManagedObjectContext!
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//管理オブジェクトコンテキストを取得する。
let applicationDelegate = UIApplication.shared.delegate as! AppDelegate
managedContext = applicationDelegate.persistentContainer.viewContext
//保存データを表示する。
displayData()
//デリゲート先に自分を設定する。
myNameTextField.delegate = self
myAgeTextField.delegate = self
}
//保存データ表示メソッド
func displayData(){
do {
//Playエンティティで保存されているデータを取得する。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
let result = try managedContext.fetch(fetchRequest) as! [Player]
//取得したデータをラベルに表示する。
var outputStr = ""
for data in result {
myLabel.text = outputStr + "," + data.name! + "," + String(describing: data.age) + "," + String(data.test)
}
} catch {
print(error)
}
}
//Returnキー押下時の呼び出しメソッド
func textFieldShouldReturn(_ textField:UITextField) -> Bool {
//キーボードをしまう
self.view.endEditing(true)
return true
}
//ボタン押下時の呼び出しメソッド
@IBAction func myPush(_ sender: UIButton) {
do {
//nameの値が同じオブジェクトを検索する。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
let players = try managedContext.fetch(fetchRequest) as! [Player]
//検索にヒットしなかった場合は新しいオブジェクトを管理オブジェクトコンテキストに格納する。
let player = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedContext) as! Player
player.name = myNameTextField.text!
player.age = Int16(myAgeTextField.text!)!
player.test = 777
//管理オブジェクトコンテキストに格納したデータを保存する。
try managedContext.save()
//データを表示する。
displayData()
} catch {
print(error)
}
}
}
に変えてみて〜〜〜〜
⒋シミュレータで実行
⒌コードを一部コメントアウト
サイト記事の内容については、以上👀
ブラッシュアップ
意味がないので、コメントアウトのコードは元に戻す
今回のコード(まとめ)
class TemporaryAttributeCoreDataViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myAgeTextField: UITextField!
@IBOutlet weak var myNameTextField: UITextField!
//管理オブジェクトコンテキスト
var managedContext:NSManagedObjectContext!
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//管理オブジェクトコンテキストを取得する。
let applicationDelegate = UIApplication.shared.delegate as! AppDelegate
managedContext = applicationDelegate.persistentContainer.viewContext
//保存データを表示する。
displayData()
//デリゲート先に自分を設定する。
myNameTextField.delegate = self
myAgeTextField.delegate = self
}
//保存データ表示メソッド
func displayData(){
do {
//Playエンティティで保存されているデータを取得する。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
let result = try managedContext.fetch(fetchRequest) as! [Player]
//取得したデータをラベルに表示する。
var outputStr = ""
for data in result {
myLabel.text = outputStr + "," + data.name! + "," + String(describing: data.age) + "," + String(data.test)
}
} catch {
print(error)
}
}
//Returnキー押下時の呼び出しメソッド
func textFieldShouldReturn(_ textField:UITextField) -> Bool {
//キーボードをしまう
self.view.endEditing(true)
return true
}
//ボタン押下時の呼び出しメソッド
@IBAction func myPush(_ sender: UIButton) {
do {
//nameの値が同じオブジェクトを検索する。
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
let players = try managedContext.fetch(fetchRequest) as! [Player]
//検索にヒットしなかった場合は新しいオブジェクトを管理オブジェクトコンテキストに格納する。
let player = NSEntityDescription.insertNewObject(forEntityName: "Player", into: managedContext) as! Player
player.name = myNameTextField.text!
player.age = Int16(myAgeTextField.text!)!
player.test = 777
//管理オブジェクトコンテキストに格納したデータを保存する。
try managedContext.save()
//データを表示する。
displayData()
} catch {
print(error)
}
}
}
地球儀ボタン追加
記事公開後、
Apple公式
さて、次回は
をレッツゴする🕺
ここら辺りから、完全に内容が乖離していきそうな内容なので〜〜〜
サイト記事をあくまでも参考に、手順どおりに作ってみた結果をまとめてく感じになると思う〜〜〜〜💦
ちなみに
一意制約を
実行しても、
なので、冒頭に、一意制約はこのプロジェクトには向かないと書いた次第💦
まあ、深く数日かけてとかで調べればわかるんだろうけど、
そこまでしても、
このプロジェクトファイルのコンセプトと反するからね〜〜〜👀
あくまでも、サイト記事に沿って、できる機能をまとめてるだけだから。
この記事が気に入ったらサポートをしてみませんか?