この記事とこのYoutubeプレイリストはとても参考になります。
NSManagedObjectはCoreDataのDataModelのあらゆるEntityを表すことが可能です。
下記のようにPerson Entityのname AttributeへString型を格納出来ます。
// appDelegateをゲット
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
// managedContextをゲット。その後はmanagedContextを介して, KVCを使ってCore Dataにsaveできる
let managedContext = appDelegate.persistentContainer.viewContext
// you can write the above in one line
// let managedContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Person", in: managedContext)!
let person = NSManagedObject(entity: entity, insertInto: managedContext)
person.setValue(name, forKey: "name")
do {
try managedContext.save()
} catch {
print(error)
}
Core DataからのFetchは以下のように出来ます。これをviewDidLoad内などで必要に応じて呼び出します。
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
do {
// returns an array of [NSManagedObject]
people = try managedContext.fetch(fetchRequest)
} catch {
print(error)
}
tableViewではこのようにBinding出来ます。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let person = people[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = person.value(forKeyPath: "name") as? String
return cell
}
ただ、この仕組みをもっと効率よく(Object-Orientedに)書くことが出来ます。
RecordというEntityがあり、そのattributeとしてname: Stringがあるとします。
EntityのCodegenは Manual/Noneを選択し、Editor -> Create NSManagedObject subclass で以下のようにsubclassを作成出来ます。


import Foundation
import CoreData
@objc(Record)
public class Record: NSManagedObject {
}
extension Record {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Record> {
return NSFetchRequest<Record>(entityName: "Record")
}
@NSManaged public var name: String
}
extension Record : Identifiable {
}
// get context
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// create new record
let newRecord = Record(context: context)
let newName = "Your Name"
newRecord.name = newName
do {
try context.save()
} catch {
print(error)
}
// to fetch
let request: NSFetchRequest<Record> = Record.fetchRequest()
do {
// this returns an array of NSManagedObject
let result = try self.context.fetch(request)
} catch {
print(error)
}
To Manyとするオブジェクトの順番をCore Dataに保存する場合はOrderedにチェックを入れます。

非標準のオブジェクト(Int配列など)をCore Dataに格納したい場合は下記のように一旦Dataとして格納し(Attribute type は Binary Dataを選択)、使用時にはオブジェクトに戻して使う、などの方法があります。
// to save
let newRecord = Record(context: self.context)
let intArray = [1,2,3]
let arrayAsString = intArray.description
let stringAsData = arrayAsString.data(using: String.Encoding.utf8)
newRecord.arrayData = stringAsData
// to fetch
let request: NSFetchRequest<Record> = Record.fetchRequest()
do {
let result = try self.context.fetch(request)
let intArray: [Int] = try JSONDecoder().decode([Int].self, from result.first!.arrayData!)
} catch {
print(error)
}
複合数のpredicateを組み合わせてcoredataを検索したり、objectを削除したりする場合は下記のようにします。
let predicateNote = NSPredicate(format: "note == %@", note.name)
let predicateID = NSPredicate(format: "chordID == %@" , NSNumber(value: id))
let predicateRootOrTop = NSPredicate(format: "rootOrTop == %@", rootOrTop.name)
let predicateFret = NSPredicate(format: "targetNoteFret == %@", NSNumber(value: fret))
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateNote, predicateID, predicateRootOrTop, predicateFret])
request.predicate = compoundPredicate
do {
let results = try managedContext.fetch(request)
if results.count == 0 {
let newBookmark = Bookmarked(context: managedContext)
newBookmark.note = note.name
newBookmark.chordID = Int32(id)
newBookmark.rootOrTop = rootOrTop.name
newBookmark.targetNoteFret = Int32(fret)
try managedContext.save()
} else {
let bookmark = results[0]
managedContext.delete(bookmark)
try managedContext.save()
}
} catch {
print(error)
}
検索結果をソートしたい場合はSort Descriptorを使います。
let sort = NSSortDescriptor(key "name", ascending: true)
let sort = NSSortDescriptor(key "name", ascending: true, selector: "customSort:")
let sort = NSSortDescriptor(key: "name", ascending: true, comparator: { (a, b) -> NSComparisonResult in
return .OrderAscending
})
fetchRequest.sortDescriptors = [sort]
オブジェクトを削除する際、そのオブジェクトにRelationshipがある場合、delete optionを適切に選ぶ必要があります。例えばownerとdeviceというEntityがあり、ownerがdevice(s)を所有しているrelationshipがあるとします。ownerオブジェクトを削除する場合、deviceのownerに対するrelationshipをどうするのか、以下の4つから選択します。
Nullify – deviceのownerはnilとする
Cascade – device(s)オブジェクトも削除する
Deny – ownerとdevice(s)にrelationshipが存在する場合は削除できない
No Action – プログラマが独自のロジックを用いたい場合

DataModelに変更を加える場合はEditor -> Add Model Versionを選択し、直前のversionから新しいmodelを作成します。

正しいModel versionを選択しないと”An NSManagedObject of class must have a valid NSEntityDescription” エラーが発生します。
