新しいサイトはこちらです↓
Cocoaの日々
※このサイトは閉鎖せずに今後も公開しておきます。
長い間ありがとうございました。
よければ新しいサイトの方も訪問してみて下さい。
橋口
2010年6月13日日曜日
サイトをリニューアルしました
投稿者 xcatsan 時刻: 22:27
2010年6月12日土曜日
CoreData - トランザクション(5) まとめ
前回までの検証結果まとめ。
NSManagedObjectContext操作まとめ
操作 | 説明 | ディスク操作 | Undo/Redoの履歴 |
---|---|---|---|
save | 現時点でのメモリの内容を保存する | 書き出し | なし |
rollback | ディスク上の内容に戻す | (必要なら)読み込み | クリア |
undo | 1つ前の操作を取り消す(操作直前の内容に戻す) | なし | なし |
redo | 次の操作をもう一回行う(取り消した操作を復活) | なし | なし |
reset | メモリの初期化(変更の破棄、読み込まれたオブジェクトの破棄) | なし | クリア |
(参考)NSManagedObjectContext Class Reference - Undo Management
今まで検証に使ったソースは GitHub からダウンロードできる。
CoreDataTransaction at 2010-06-12 from xcatsan's SampleCode - GitHub
2010年6月11日金曜日
CoreData - トランザクション(4) reset
-[NSManagedObjectContext reset] を試す。
コードを追加し、
ボタンに紐づける。
実行。resetボタンを押すと、
データが消える。
これは NSManagedObjectContext(メモリ)上のデータが消えただけで、ディスク上のデータは残っている。
試しに reload ボタンを追加する。
ボタンが押されたら、NSArrayController を使っているので prepareContent を投げてみる。
すると reset で一旦消えた後、
reloadボタンで復活。
reset するとそれまでに読み込まれた NSManagedObject がすべて開放される(ドキュメントでは "forgotton" という表記)。当然ながら直前の変更状態はディスクには残らず破棄されてしまう。Undo/Redo履歴もクリア。用途としては NSMangedObjectContext のインスタンスを別の用途で使いまわす場合の初期化に使うことが考えられる。
2010年6月10日木曜日
CoreData - トランザクション(3) undo と redo
undo と redo をやってみる。
まずアクションメソッドを用意する。
Interface Builder を開き、Undo/Redoのボタンを追加する。これを先程のメソッドに紐づける。
実行する。確かに Undo/Redo が効いている。なお標準でメニューのUndo/Redoが FirstResponderにひもづけられており、実は今回のボタンを用意しなくてもメニューから Undo/Redoが行えた。
save と rollback の関係だが次のようになっていた。
(1) save後、Undo/Redo操作 は行える
(2) rollback後、Undo/Redo操作は行えない(操作履歴がクリアされる)
2010年6月9日水曜日
CoreData - トランザクション(2) rollback
rollback を試してみよう。前回のサンプルに Rollback ボタンを追加する。
実行してみよう。
新規にレコードを追加し、入力したところで Rollback ボタンを押す。
すると新規レコードが取り消されるのがわかる。
複数の操作も試してみよう。
まず新規レコードを追加し
元からあったレコードを修正し
1レコード削除する
そして Rollback
元に戻った。
2010年6月8日火曜日
CoreData - トランザクション(1) 準備
CoreData のトランザクションについて調べてみる。
NSManagedObjectContext では Undo Management としていくつかメソッドが用意されている。
NSManagedObjectContext Class Reference - Undo Management
これらの挙動を試す簡単なサンプルプログラムを組んでみよう。
今回はまずレコードの表示、追加、削除、変更ができるプログラムを組む。
まず Xcodeで新規プロジェクトを作る。このとき "Use Core Data for storage" にチェックを入れておく。
ビューを用意する。NSTableView を作り author と titile 列を作る。
モデルとビューの紐付けに NSArrayController を使う。
Modeを Entity とし、Entity Name に Book を指定する。これでモデルとつながった。
NSTableView内の NSTableColumnのバインディング設定を開、Array Controller を指定する。
これで MVCがつながった。
モデル(Book) ← コントローラ(ArrayController)←ビュー(NSTableView/NSTableColumn)
ただし CoreDataを扱うにはもう一手間必要で ArrayController に NSManagedObjectContext を渡す必要がある。今回 NSManagedObjectContextはコード内で生成している為、Interface Builderでは接続できない。この為、コード上で紐付けておく。
arrayController はあらかじめ IBOutlet で定義し、InterfaceBuidlerで紐付けておく。
CoreDataTransaction_AppDelegate.h
モデル(Book) ← コントローラ(ArrayController)←ビュー(NSTableView/NSTableColumn) ↓ CoreData(NSManagedObjectContext)
これでベースができた。後はデータ追加と削除のコードを付けておこう。
[+][ー]ボタンを作る。
NSArrayController には add: と remove: が用意されているので、それぞれ接続する。
これだけで新規追加と削除が行えるようになる。
さて動かしてみよう。追加、変更、削除が行える。
File メニューから Save を選択するとディスク(XML)に保存ができる。これは新規作成時のテンプレートが saveAction: を実装していて、メニューのSaveと紐づいている為。
ソース:
CoreDataTransaction at 2010-06-08 from xcatsan's SampleCode - GitHub
今日はここまで。
2010年6月7日月曜日
カテゴリでクラスメソッド定義
カテゴリはクラスメソッドもいける。
こうなら、
普通に呼び出せる。
ファクトリメソッドなどの追加に使えそうだ。
- - -
近日ブログのリニューアル予定(URLが変わります)。
2010年6月6日日曜日
今週のCocoa情報(6/6) - 今週気になった Cocoaプログラミング情報の紹介
what are alternatives to throwing exceptions in objective c - Stack Overflow
@throw よりも NSError を使う方が "the Apple recommended pattern" とのこと。確かに Cocoa Framework では例外より NSErrorを使う方が多い。
iPhone開発で便利なcocoa.vim - hellkite 日記と雑記とメモ。
MacVimとcocoa.vimで世界が変わった - Meltdown Countdown
VimでCocoa開発する話題。普段 PHPアプリなどは vimを使っているので気になる。
Cocoa nonatomic properties - Stack Overflow
プロパティ設定で "nonatomic"をつけない場合、ロック/アンロックのオーバーヘッドがかかる。
- - - -
今回も少なかった。
2010年6月5日土曜日
CoreData - Object ID(その5)情報
(前回)Cocoaの日々: CoreData - Object ID(その4)Object ID から NSManagedObject を取得する #2
NSManagedObjectID についての情報など。
NSManagedObjectID into NSData - Stack Overflow
NSURL へ変換後、NSKeyedArchiver を使い NSData へ格納。
Cocoa with Love: Safely fetching an NSManagedObject by URI
NSManagedObjectIDに関して簡潔だがわかりやすい説明。URIから NSManagedObject を取得するカテゴリを紹介している。
@implementation NSManagedObjectContext (FetchedObjectFromURI) - (NSManagedObject *)objectWithURI:(NSURL *)uri { : }
例外を出さず、確実に非faultのオブジェクトを取得する作りになっている。
Core Data Programming Guide: Using Managed Objects
Managed Object IDs and URIs
Mac Dev Center の解説。
2010年6月4日金曜日
CoreData - Object ID(その4)Object ID から NSManagedObject を取得する #2
(前回)Cocoaの日々: CoreData - Object ID(その3)Object ID から NSManagedObject を取得する
Object ID から NSManagedObject を取得するメソッドは、前回の -[objectWithID:] を含め3つある。
クラス:NSManagedObjectContext
- (NSManagedObject *)objectWithID:(NSManagedObjectID * - (NSManagedObject *)objectRegisteredForID:(NSManagedObjectID *)objectID - (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error
今回はこれらの動作を比較してみる。
1. objectWithID: の動作
(1) まず Object ID に該当するオブジェクトが、NSManagedObjectContext内に登録されているかチェックする。登録されている場合は、そのオブジェクトを返す(非Fault)。
(2) 登録されていない場合はPersistent Storeからフェッチする。
a) 該当レコードが存在する場合
フェッチしたオブジェクトを返す(Fault)
b) 該当レコードが存在しない場合
例外がスローされる。
(例) CoreDataObjectID[12483:80f] An uncaught exception was raised CoreDataObjectID[12483:80f] CoreData could not fulfill a fault for '0x226340 <x-coredata://677CA547-4D80-417A-8810-70847FB0375D/Book/p20>' CoreDataObjectID[12483:80f] *** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x226340 <x-coredata://677CA547-4D80-417A-8810-70847FB0375D/Book/p20>'' *** Call stack at first throw: ( 0 CoreFoundation 0x9253bbda __raiseError + 410 1 libobjc.A.dylib 0x97efc509 objc_exception_throw + 56 2 CoreData 0x9469a00e _PFFaultHandlerLookupRow + 174 3 CoreData 0x94699f57 -[NSFaultHandler fulfillFault:withContext:] + 39 :
2. objectRegisteredForID: の動作
NSManagedObjectContext内に登録されているかのみチェックする。
a) Object ID に該当するオブジェクトがNSManagedObjectContext内に登録されている場合
該当するオブジェクト(NSManagedObject)を返す(非Fault)。
b) 該当レコードがNSManagedObjectContext内に登録されていない場合
nil を返す。例外はスローされない。
3. existingObjectWithID:error: の動作
このメソッドは Mac OS X v10.6 から追加された(iPhone OS では 3.0以降)。基本動作は objectWithID: と同じだがヒットしなかった時は例外はスローせず、nilを返す。また errorから原因を知ることができる。
(1) まず Object ID に該当するオブジェクトが、NSManagedObjectContext内に登録されているかチェックする。登録されている場合は、そのオブジェクトを返す(非Fault)。
(2) 登録されていない場合はPersistent Storeからフェッチする。
a) 該当レコードが存在する場合
フェッチしたオブジェクトを返す(非Fault)※ここは試した時には何故か Faultにならなかった(ので、非Faultにしてある)。
b) 該当レコードが存在しない場合
nilを返す。この時、errorに原因が格納される。
(例)Error Domain=NSCocoaErrorDomain Code=133000 UserInfo=0x21e6f0 "Attempt to access an object not found in store."
サンプル:CoreDataObjectID at 2010-06-04 from xcatsan's SampleCode - GitHub
※コメントを修正することで上記3種類が試せるようになっている(かなりわかりづらいが)。
- - - -
Mac OS X v10.6 / iPhone OS 3.0 では existingObjectWithID:error: が一番使い勝手がいい。
2010年6月3日木曜日
CoreData - Object ID(その3)Object ID から NSManagedObject を取得する
Object ID の URI から NSMangedObject を取得することができる。ステップは2つ。
(1) -[NSPersistentStoreCoordinator managedObjectIDForURIRepresentation:] を使い、NSManagedObjectID を取得する (2) -[NSManagedObjectContext objectWithID:] に(1)の結果を渡し、NSManagedObject を取得する。
NSPersistentStoreCoordinator Class Reference - managedObjectIDForURIRepresentation:
NSManagedObjectContext Class Reference - objectWithID:
やてみよう。
サンプル:CoreDataObjectID at 2010-06-03 from xcatsan's SampleCode - GitHub
前回までのサンプルに次の2つの修正を加える。
1. アプリ終了時に選択していたレコードの Object ID (URI) を User Defaults へ保存する。
実行してみよう。まず行を選択し、アプリを終了する。
続いてアプリを起動し、ログを確認する。
出た。
- - - -
一連の検証で Object ID がアプリの状態保持と復帰(レジューム)に利用できそうなことがわかった。
2010年6月2日水曜日
CoreData - Object ID(その2)モデルのバージョンを変える
モデルのバージョンを変えると Object ID は変化するのか?試してみた。
バージョンを追加後(v2)、createdを追加した。
マッピングモデルを追加し、現在のバージョンを先程追加したもの(v2)に設定する。
(参考)Cocoaの日々: CoreData - マイグレーション
ビルド後に実行してみる。
(なお実行時にエラーが出る場合は、クリーニングしたのち再ビルドすると良い)。
結果は変わらず。これはまあ当然か。
1レコード追加してみる。
UUIDの部分(677CA547-...)は変わらないようだ。モデルのバージョンによって変化しないことがわかった。
SQLite DB の中身。
sqlite> select * from z_metadata;
1|677CA547-4D80-417A-8810-70847FB0375D|bplist00? _NSStoreModelVersionIdentifiers_NSPersistenceFrameworkVersion_NSStoreModelVersionHashes[NSStoreType_ NSStoreModelVersionHashesVersion__NSAutoVacuumLevel???
メタ情報に変化はないようだ。最初のカラム名に Version とついていたので、レコードが追加されると思ったがそうはならないようだ。
サンプル:
CoreDataObjectID at 2010-06-02 from xcatsan's SampleCode - GitHub
2010年6月1日火曜日
CoreData - Object ID(その1)NSManagedObjectID
NSManagedObject の Object ID
NSManagedObjectには、オブジェクトを一意に識別する為にObject ID割り振られている。この ID は NSManagedObjectID型として定義されていて、-[NSManagedObject objectID] で取得できる。
NSManagedObject Class Reference - objectID
NSManagedObjectID
このNSManagedObjectIDは次のメソッドを持っている。
- (NSEntityDescription *)entity - (BOOL)isTemporaryID - (NSPersistentStore *)persistentStore - (NSURL *)URIRepresentation
NSManagedObjectID Class Reference
saveするまでの間、Object ID は一時扱いとなる。その場合、-[isTemporaryID] が YES を返す。
-[URIRepresentation]は Object ID のURI表記を返す。
URIRepresentation の例
x-coredata://1C336A08-41AD-48E9-8A3F-8AFF17244055/Book/p1
(以下推測)
x-coredata | プロトコル
1C336A08-41.. | モデルの UUID(もしくは類似のID)
book | エンティティ名
p1 | 'p' + プライマリキー
なおsave前の(一時的な)Object ID の URIRepresentation は次のようになる。
x-coredata:///Book/t7839D4D0-A144-4C95-B14C-33AEFAF337632
リファレンスによれば、Object ID は他のアプリケーションも含めユニークなものになるとのこと。終了時に plistへ保存しておいて、次回起動時にこのIDから前回使っていた情報を取得するなんて用途に使える。
サンプル
Object ID を見るための簡単なサンプルを用意した。
ソース:CoreDataObjectID at 2010-06-01 from xcatsan's SampleCode - GitHub
モデルの定義はこんな感じ。
実行するとテーブルが現れる。Addで追加ができる。この時点ではまだテンポラリなIDが割り振られている。
saveすると正式なものが割り振られる。
この時の SQLiteの中身。
$ sqlite3 storedata SQLite version 3.6.12 Enter ".help" for instructions sqlite> .schema zbook CREATE TABLE ZBOOK ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZTITLE VARCHAR, ZAUTHOR VARCHAR ); sqlite> select * from zbook; 1|1|1|Book1|Neko sqlite> sqlite> .schema z_metadata CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB); sqlite> select * from z_metadata; 1|677CA547-4D80-417A-8810-70847FB0375D|bplist00? _NSStoreModelVersionIdentifiers_NSPersistenceFrameworkVersion_NSStoreModelVersionHashes[NSStoreType_ NSStoreModelVersionHashesVersion__NSAutoVacuumLevel???
ObjectID に含まれるUUIDが Z_METADATAに格納されているのがわかる。
2010年5月31日月曜日
Objective-C カテゴリでプロパティ
例えばこんなクラスがあるとする。
Customer.h
birthdate(誕生日)から現時点での年齢を計算したいのだが、これをプロパティとして取得できるようにしたい。これをカテゴリで実装する。
こんな感じ。
Customer+Extension.h
追加メソッドをプロパティとして実装できる。
これを使う場合はこんな感じ。
参考)
Calculate age in objective-c | I ticked the wrong box
Cocoaの日々: CoreData - Xcodeでモデルクラスを自動生成する
投稿者 xcatsan 時刻: 23:53
ラベル: category, objective-c
2010年5月30日日曜日
今週のCocoa情報(5/30) - 今週気になった Cocoaプログラミング情報の紹介
How to get macos Log-in User Name in objective-c - Stack Overflow
Q)ログイン中のユーザ名を取得するには?
A)NSUserName() を使う
Foundation Functions Reference
他にも
NSFullUserName
NSHomeDirectory
NSHomeDirectoryForUser
なんてものがある。
Break on EXC_BAD_ACCESS in XCode? - Stack Overflow
EXC_BAD_ACCESS 解決に NSZombieEnabled を使う件。
CocoaDev: NSZombieEnabled
Cocoa Singleton conventions - Stack Overflow
Q)シングルトンパターンを使う場合のメソッド名は default〜 と shared〜 のどちらが良いか。
(例) NSSingletonObject *so = [NSSingletonObject defaultSingleton]; VS NSSingletonObject *so = [NSSingletonObject sharedSingleton];
A)
shared〜 :このメソッド以外(お約束として)インスタンス生成ができない場合(真の?シングルトン)
default〜:自分でも作成可能だが、クラスがデフォルトインスタンスを提供する場合
なるほど。
参考)
Cocoa Fundamentals Guide: Cocoa Design Patterns - Singleton
how to rename or change file name case on the same location in objective-c - Stack Overflow
Q)ファイル名の大文字小文字を変換したい
(例)abc.txt => (ABC.txt or Abc.txt or abc.TXT or abc.Txt)
- (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handlerは、この用途では使えない。
A)ヒント↓
Possible Bug in NSFileManager -moveItemAtPath:toPath:error: | Cocoabuilder
systemコール "rename" を使ったらどうか、とのこと。
-fileSystemRepresentation で C文字列が取得できるのでそれを使う。
OCUnitの使い方(Cocoa Application 編) ([SM gakusyuu];)
環境の用意からテストケースの作成までの日本語解説。図入りで分かりやすい。
Cocoa Fundamentals Guide: Cocoa Design Patterns
一つ前の情報で紹介したものだが、こんなものがあったのか。
2010年5月29日土曜日
CoreData - テーブルの件数を取得する(SQL確認)
以前、別のブログで CoreDataでテーブルの件数を取得する記事を書いた。
Cocoa Touch の日々: CoreData - テーブルの件数を取得する
発行される SQLを調べてなかったので確認してみた。
SELECT COUNT(*) FROM ZSTYLETAG t0※iPhoneSDK3.1.3にて
無駄なSQLは出ていないようだ(当然か)。
2010年5月28日金曜日
CoreData - SQLite の LIMIT
-[NSFetchRequest setFetchBatchSize:] で指定したサイズ値がフェッチ時に発行される SQLの LIMIT値となる。
例えば
[fetchRequest setFetchBatchSize:20];とするとSQLはこうなる。
SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZMODIFIEDDATE, t0.ZFEE, t0.ZMEMO, t0.ZCREATEDDATE, t0.ZOPERATEDDATE, t0.ZCUSTOMER FROM ZKARTE t0 WHERE t0.Z_PK IN (?,?,?) ORDER BY t0.ZOPERATEDDATE DESC LIMIT 20
3件ヒットするケースで、サイズを1とすると
[fetchRequest setFetchBatchSize:1];
こうなる。
sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZMODIFIEDDATE, t0.ZFEE, t0.ZMEMO, t0.ZCREATEDDATE, t0.ZOPERATEDDATE, t0.ZCUSTOMER FROM ZKARTE t0 WHERE t0.Z_PK IN (?) ORDER BY t0.ZOPERATEDDATE DESC LIMIT 1 sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZMODIFIEDDATE, t0.ZFEE, t0.ZMEMO, t0.ZCREATEDDATE, t0.ZOPERATEDDATE, t0.ZCUSTOMER FROM ZKARTE t0 WHERE t0.Z_PK IN (?) ORDER BY t0.ZOPERATEDDATE DESC LIMIT 1 sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZMODIFIEDDATE, t0.ZFEE, t0.ZMEMO, t0.ZCREATEDDATE, t0.ZOPERATEDDATE, t0.ZCUSTOMER FROM ZKARTE t0 WHERE t0.Z_PK IN (?) ORDER BY t0.ZOPERATEDDATE DESC LIMIT 1
LIMIT 1 のSQLが件数分(3件)発行される。
※iPhone OS 3.1.3 用コードで確認
2010年5月27日木曜日
CoreData - 検索見本(NSManagedObjectを条件に検索)
NSPredicate を使う。
例えば、Customer(マスタ)<−−−>> Karte(ディティール)というモデルがあり、特定の Customer に紐づく Karteの一覧を取得する場合。
オブジェクトが条件の場合でも上記のように等号条件として書ける。
SQLite のログはこう。
SELECT 0, t0.Z_PK FROM ZKARTE t0 WHERE t0.ZCUSTOMER = ? ORDER BY t0.ZOPERATEDDATE DESC SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZMODIFIEDDATE, t0.ZFEE, t0.ZMEMO, t0.ZCREATEDDATE, t0.ZOPERATEDDATE, t0.ZCUSTOMER FROM ZKARTE t0 WHERE t0.Z_PK IN (?,?,?) ORDER BY t0.ZOPERATEDDATE DESC LIMIT 20
最初に Customer を条件にして合致する Karteの PK(Primary Key)を取得している。そして、取得した PK を SELECT ...IN( ) の条件として Karteのデータを得る。
# 合致する Karte が1万件あったら、IN (1万件の PK)となるのだろうか。
(追記)通常、LIMIT 制限するのでそんなことはおこらない。
※iPhone OS 3.1.3 用コードで確認
2010年5月26日水曜日
CoreData - マイグレーション
モデルの修正
CoreDataのマイグレーションを試してみた。通常モデルに修正を加えると、直前に作成したSQLiteDBは使えず実行時エラーが出る。この場合、SQLiteDBを一旦削除する必要がある。当然データの引き継ぎはできない。
エラーログ:
CoreDataでのデータマイグレーション
CoreDataにはマイグレーションの仕組みが用意されていて、これを利用することができる。
Core Data Model Versioning and Data Migration Programming Guide: Introduction to Core Data Model Versioning and Data Migration Programming Guide
属性値の追加など簡単な変更については自動マイグレーションが使えるようだ。
Core Data Model Versioning and Data Migration Programming Guide: Lightweight Migration
自動マイグレーションは下記が参考になる。
Core Dataの自動マイグレーション | hippos-lab::blog
試してみよう。
自動マイグレーション
1. モデルバージョンを追加する。
CoreDataRelationship_DataModel 2.xcdatamodel が追加された。
2. モデルを変更する。
今回は新しいバージョンの方に属性 published (NSData)を追加する。
3. Mapping Model を作成する。
「差分を表示」を使うと新旧モデルの比較ができる。下図は published が追加されたことを表している。
5. 属性マッピングを設定する
published はオプションなのでそのままでも問題ないのだが、試しに created の値を使うようにしてみた。
6. マイグレーションコードを追加する。
options: にマイグレーション用オプションを追加する。
7. 現在のバージョンを設定する。
新バージョンを選択後にメニューから設定する。
チェックがつく。
8. 実行
エラーが出なくなった。SQLite の中をみてみる。
sqlite> .schema ZBLOGENTRY
CREATE TABLE ZBLOGENTRY ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZPUBLISHED TIMESTAMP, ZCREATED TIMESTAMP, ZTITLE VARCHAR, ZCONTENT VARCHAR );
ZPUBLISHED が追加されている。データも ZCREATEDの値がコピーされているのが確認できた。
sqlite> select * from ZBLOGENTRY; 1|2|5|296460106.418831|296460106.418831|iPad 5/28発売|かくかくしかじか 2|2|8|296460106.418047|296460106.418047|CoreData のリレーションしっぷについて|かくかくしかじか
飛ばしバージョンアップ (1→3)
さらに続けてバージョン3を作る。その上で、バージョン1のデータがどうなるかをみてみよう。
まずバージョン3のモデルを作る。
BlogEntryへ visible(BOOL)を追加してみた。
Mappin Model を作る。ソースはバージョン2、デスティネーションはバージョン3にした。
sqlite> .schema ZBLOGENTRY
CREATE TABLE ZBLOGENTRY ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZVISIBLE INTEGER, ZPUBLISHED TIMESTAMP, ZCREATED TIMESTAMP, ZTITLE VARCHAR, ZCONTENT VARCHAR );
sqlite> select * from ZBLOGENTRY; 1|2|4|1|296460106.418831|296460106.418831|iPad 5/28発売|かくかくしかじか 2|2|6|1|296460106.418047|296460106.418047|CoreData のリレーションしっぷについて|かくかくしかじかvisibleが追加されているのが確認できた。
さて次はいよいよ1→3のマイグレーションを試みる。とっておいたバージョン1のSQLIteDBファイルをおいて、現在のモデルのバージョンを3として実行する。
結果はOK。
おお賢い。おそらく 1→2, 2→3 と自動的にマイグレーションを適用しているのだろう。
sqlite> .schema ZBLOGENTRY
CREATE TABLE ZBLOGENTRY ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZVISIBLE INTEGER, ZPUBLISHED TIMESTAMP, ZCREATED TIMESTAMP, ZTITLE VARCHAR, ZCONTENT VARCHAR );
sqlite> select * from ZBLOGENTRY; 1|2|4|1|296460106.418831|296460106.418831|iPad 5/28発売|かくかくしかじか 2|2|6|1|296460106.418047|296460106.418047|CoreData のリレーションしっぷについて|かくかくしかじか
気がついた点
バックアップファイルが自動生成される
SQLite のDBファイルがマイグレーション直前にコピーされ、バックアップがとられるようだ。
CoreDataRelationship.db CoreDataRelationship~.db ←バックアップ
NSInferMappingModelAutomaticallyOption
-[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:] で渡すオプション NSInferMappingModelAutomaticallyOption は Mac OS v10.6 以上なので、v10.5 では使えない。
調べたところ iPhone は 3.0 以上で利用できるようだ。
2010年5月25日火曜日
CoreData - Xcodeでモデルクラスを自動生成する
自動生成方法
モデルエディタでモデルを選択した後、メニューから「ファイル > 新規ファイル」を選ぶと管理クラスオブジェクトが選べるようになるのでこれを選択する。
生成されるクラス
BlogEntry.h
BlogComment.h
Tag.h
モデル変更時の対応
モデルの変更は、開発中のみならずシステム(アプリ)の運用・保守中にも必ず起こる。独自メソッドを自動生成クラスへ追加すると、その度にコードを追加しなければならなくなるので、これを避ける為にカテゴリを使う。
自動生成の自動化
mogenerator というソフトが公開されている。
nvie.com » Blog Archive » Automatically generate classes for your Core Data data model
これは未検証だが、使える内容ならビルドフェーズに組み込むと便利かもしれない。