CoreDataの属性設定項目OptionalチェックボックスとNSManagedObjectプロパティOptionalの違い

プログラミング独学

Optionalという同じ言葉。ここで私自身の思い込み、頭の硬さが出てしまったと思います。「CoreDataの属性設定項目OptionalチェックボックスNSManagedObjectプロパティOptional」は分けて考えることが必要でした。すぐに忘れてしまうCore Dataの仕組みを思い返せる様書きます。

伝えたい事がうまくまとまっているか不安ですがご了承下さい。

Attribute(属性)

「属性の設定項目画面」Optionalチェックボックスの意味

「属性の設定項目画面Optionalチェックボックス」のファーストインプレッション

属性設定項目画面Optionalチェックボックス。このOptionalをオンにすると自動生成出来るオブジェクトのプロパティに影響しプロパティに「?」が付きオプショナルになるのだろうと思った。

検証

NewProjectを「Use Core Data」チェック付きで作成。

PersonとageのAttribute(属性)を作成。

設定は変更しない。Optionalにはチェックがついたまま。

「Codegen」をCalss DefinitionからManual/Noneに変更。

クラスを自動生成

Edit -> Create NSManagedObject Subclass… を選択し

Person+CoreDataClass

import Foundation
import CoreData

@objc(Person)
  public class Person: NSManagedObject {

}

Person+CoreDataClassProperties

import Foundation
import CoreData


extension Person {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Person> {
        return NSFetchRequest<Person>(entityName: "Person")
    }

    @NSManaged public var name: String?
    @NSManaged public var age: Int16

}

extension Person : Identifiable {

}

疑問

「属性設定項目画面Optionalチェックボックス」で「name」「age」共にOptionalにチェックを入れたにも関わらず、「name」は?がついてオプショナル、「age」は?無しの非オプショナル。

ここで混乱してしまう

「属性設定項目画面Optionalチェックボックス」とPerson Classのオプショナルは違うもの

文献を調べてみました。

「Swift + Core Dataによる iOSアプリプログラミング」にこう書かれているのを見つけました。

属性設定項目画面Optionalチェックボックス」について

なお、ここでの「オプショナル」は属性です。Swiftのオプショナル型とは異なるので混同しないように注意してください。

Swift + Core Dataによる iOSアプリプログラミング P109

確かに自分も同じことのように捉えてしまっています。自分の中で違いが明確に出来ていないことが原因の1つと思います。

CoreDataモデル属性のOptionalとクラス型のOptionalは、異なるものです。

  • CoreDataモデル属性の設定 において、「Optional」という設定があります。これは、永続ストアがnil(値が設定されていない)を許可するかどうかを示すものです。「Optional」を設定すると、永続ストアにnilを格納することができます。
  • クラス型のOptional: Swiftでは、変数やプロパティに「Optional」を付けることができます。これは、変数やプロパティがnilを許可するかどうかを示すものです。「Optional」を付けた変数やプロパティはnilを格納することができます。

ということで、CoreDataモデル属性のOptionalとクラス型のOptionalは、同じ「nilを許可するかどうか」という意味を持つものですが、異なるものであるということになります。

「Optional」を設定することで、永続ストアにnil(値が設定されていない)を格納することができます。

また、Optionalを設定しない場合、永続ストアにnilを格納することはできず、必ず値が設定されていなければなりません。これは、CoreDataのデータモデルで定義された規約に従ったデータの管理を保証するための措置です。

CoreDataモデル属性のOptionalは、開発者がCoreDataを使ってアプリケーションを作成する際に、データモデルを定義する上で重要な概念の一つであり、使い方によってはアプリケーションのデータ管理やエラーハンドリングに大きな影響を与えることもあります。

実験1

  • nameの「属性の設定項目画面」Optionalチェック無し
  • Default Value DefaultStringをチェック有り “Default”

へ変更してみます。

そして、

Person+CoreDataClass

Person+CoreDataClassProperties

を一旦削除し再度自動作成しましたが、相変わらずプロパティーnameは String?となっています。

ageには?はありませんが永続ストアに「nil」を書き込んでみたいので?を付けてみました。

すると、エラーが

Property cannot be marked @NSManaged because its type cannot be represented in Objective-C

Objective-Cでは型が表現できないため、プロパティに@NSManagedを付けることができない。

ageの属性設定Optionaをlチェック有りなのにエラーは消えませんでした。ここはやはり違うものということでしょうか。

実験2

  • nameの「属性の設定項目画面」Optionalチェック無し
  • Default Value DefaultStringをチェック無し

と、

  • nameの「属性の設定項目画面」Optionalチェック有り
  • Default Value DefaultStringをチェック無し

この、両設定にnilを書き込んでみます。

nameの「属性の設定項目画面」Optionalチェック無し

save()の直前でブレークポイントを設置

name = nilで実行した結果。

エラー

“Error — CoreData save: Error Domain=NSCocoaErrorDomain Code=1570 \”name is a required value.\” UserInfo={NSValidationErrorObject=<Person: 0x6000012f2490> (entity: Person; id: 0x6000031e1080 <x-coredata:///Person/tA583B071-BAC7-40F9-AFCE-D39247F526F52>; data: {\n    age = 0;\n    name = nil;\n}), NSLocalizedDescription=name is a required value., NSValidationErrorKey=name, NSValidationErrorValue=null}, [\”NSValidationErrorKey\”: name, \”NSLocalizedDescription\”: name is a required value., \”NSValidationErrorObject\”: <Person: 0x6000012f2490> (entity: Person; id: 0x6000031e1080 <x-coredata:///Person/tA583B071-BAC7-40F9-AFCE-D39247F526F52>; data: {\n    age = 0;\n    name = nil;\n}), \”NSValidationErrorValue\”: <null>]”

XCode

save()を実行直後にエラー

name = “New Name”で実行したらエラーは無し。

nameの「属性の設定項目画面」Optionalチェック有り

name = nilで実行した結果。エラー無し。

save()で永続ストアへnilを書き込めた様です。

結果

「属性の設定項目画面」Optionalは永続化ストアにnilが書き込めるのかどうかを決定する場所。

NSManegedObject Personのプロパティの?オプショナルとはやはり別物という事と理解し進めていきます。

  • SwiftUI これからのアーキテクチャはこれに決めた「ActorStreamMVVM」

  • ActorStreamMVVM 2025

  • GitHub Copilot for Xcode で Language server error: Server error: 1001 Could not log in with device flow on https:// HTTP 404 nil とエラーが出てログイン出来なかった時

  • SwiftUI .sheet(item でのView表示後キーボード表示でシートが消えた!

コメント

タイトルとURLをコピーしました