本記事は下記を参考にしています。
開発環境
> xcodebuild -version Xcode 13.1 Build version 13A1030d
Core Data とは
Persist or cache data on a single device, or sync data to multiple devices with CloudKit.
https://developer.apple.com/documentation/coredata
今日は保存と取得をやってみる。
Entities, Attributes の定義の追加
~.xcdatamodeld
で GUI 上で設定。
Xcode の Utility Area で確認できる Codegen はデフォルトの Class Definition。
コード
class SceneDelegate: UIResponder, UIWindowSceneDelegate { ... func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). guard let _ = (scene as? UIWindowScene) else { return } if let rootVC = window?.rootViewController as? ViewController { rootVC.container = persistentContainer } } ... // MARK: - Core Data stack lazy var persistentContainer: NSPersistentContainer = { /* The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. */ let container = NSPersistentContainer(name: "Test20220329_coredata") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { // Replace this implementation with code to handle the error appropriately. // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. /* Typical reasons for an error here include: * The parent directory does not exist, cannot be created, or disallows writing. * The persistent store is not accessible, due to permissions or data protection when the device is locked. * The device is out of space. * The store could not be migrated to the current model version. Check the error message to determine what the actual problem was. */ fatalError("Unresolved error \(error), \(error.userInfo)") } }) return container }() }
Setting Up a Core Data Stack には AppDelegate での初期化が紹介されているが、iOS13以上だとwindowが無くてエラーになる。
iOS13以上では AppDelegate ではなく、SceneDelegate でやるのがスムーズらしい。*1
final class ViewController: UIViewController { var container: NSPersistentContainer! override func viewDidLoad() { super.viewDidLoad() guard container != nil else { fatalError("This view needs a persistent container.") } // 保存 let context = container.viewContext let idol = NSEntityDescription.insertNewObject(forEntityName: "Idol", into: context) as! Idol idol.name = "櫻木 真乃" idol.height = 155 context.insert(idol) try! context.save() // 取得 // let context = container.viewContext // let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Idol") // let idols = try! context.fetch(request) as! [Idol] // for idol in idols { // print(idol.name, idol.height) // Optional("櫻木 真乃") 155 // } } }
参考
- Core Data | Apple Developer Documentation
- Even if it is implemented accordin… | Apple Developer Forums
*1:Apple Developer Forumで質問したらすぐ返ってきた。感謝。 https://developer.apple.com/forums/thread/703173