きりかノート 3冊め

おあそびプログラミング

まわり道な方法で CoreData の属性の初期値を設定する

CoreData のモデルをコードから変更する 件の検証も兼ねて実験。

通常 CoreData で固定値以外の初期値を設定するには、NSManagedObject#awakeFromInsert を使うのが定石だ。ちなみに固定値は、NSAttributeDescription#defaultValue により設定されている。このへんは HMDT 3rd(赤) のChapter 7を読めば書いてある。

じゃあさ、NSAttributeDescription のサブクラスで defaultValue をオーバーライドしてやって、それをモデルが持つようにすればその defaultValue が呼ばれて好きな初期値が設定できるんじゃない?と考えた。ここで検証したいのは

  • NSAttributeDescription#defaultValue は毎回呼ばれるのか。NSManagedObjectContext にキャッシュされてればアウトだ。
  • コード上で本当に NSManagedObjectModel が変更できるか

の2点だな。

結論から先に言うと、両方とも問題なしだった。じゃ、今回の実験内容。

Objective-C だとめんどうなので、RubyCocoa でやった。

まずは、NSAttributeDescription のサブクラス

 class MyAttrDescription < OSX::NSAttributeDescription
def defaultValue
return OSX::NSDate.date
end
end

こんだけ。現在日時が初期値になるものだ。

次はドキュメント。これは NSPersistentDocument#managedObjectModel をオーバーライド。なんかぐだぐだだけど気にしない。

 class MyDocument < OSX::NSPersistentDocument
# snip
@@model = nil

def managedObjectModel
unless @@model
@@model = super_managedObjectModel
@@model.entities.each do |ent|
# 元の属性の定義を削除
attr_org = ent.attributesByName['createDate']
props = ent.properties.mutableCopy
props.removeObject(attr_org)
# 新しい属性の定義を追加
attr_new = MyAttrDescription.alloc.init
attr_new.setName('createDate')
attr_new.setAttributeType(OSX::NSDateAttributeType)
props.addObject(attr_new)

ent.setProperties(props)
end
end
return @@model
end

# snip
end

これで createDate という名前の属性は初期値が現在日時になる。今日の実験はこれまで。