Navigation-based Applicationテンプレートを選ぶ場合はCore Dataを使うかどうか選択できるようになってるけど、View-basedではチェックボックスが出てこない。
それならば自分で実装しようということになるのだけれど、うーんうーんって感じになる場合が多いと思うの。
なので手順を書いておく。
Xcode 3.2.4 and iOS SDK 4.1 で試してる。
古いバージョンとか新しいバージョンのこと考えてない。
新規プロジェクトをView-based Applicationを選択して名前をMyCDataとして作成してます。
僕がやったポイント。
- CoreData.frameworkを追加
- DataModel(.xcdatamodel)ファイルを新規作成
- DataModelにエンティティ作ってプロパティを追加
- .xcdatamodelを.xcdatamodeldにバンドル
- Managed Object Class(NSManagedObjectサブクラス)ファイルを新規作成
- おまじないのコード(NSManagedObjectContextなどを用意)
- 後は普通にコード書く
- データの読み込みや追加などは、用意したコンテクスト(NSManagedObjectContext)を通じて実行
1.Frameworksグループを右クリック>追加>既存のフレームワーク>CoreData.frameworkを追加
2.Resourcesグループを右クリック>追加>新規ファイル>DataModelを選択>MyCData.xcdatamodelと名前付けて次へでそのまま完了。
3.MyCData.xcdatamodelにエンティティPersonを追加して、そのプロパティにageとnameを追加。
データ型を
age は Int16
name は String
とした。
4.MyCData.xcdatamodelを選択した状態で、設計>データモデル>モデルバージョンを追加。
MyCData.xcdatamodeldにMyCData.xcdatamodelがバンドルされた形になる。
MyCData.xcdatamodeldの中にxcdatamodelファイルが1つ追加されるけどいらないので削除する。
※この4.をやらないで対応する方法もあるけれどそれは書かない。将来的にモデルの変更(プロパティの追加など)がされる可能性を考えれならこれやっとけばいいじゃん、必要になるでしょってことで。
5.エンティティPersonを選択した状態でファイル追加をするとManaged Object Classが選べるので、そのまま完了するとPerson.h/.mが追加される。
- //
- // Person.h
- //
- #import <CoreData/CoreData.h>
- @interface Person : NSManagedObject
- {
- }
- @property (nonatomic, retain) NSNumber * age;
- @property (nonatomic, retain) NSString * name;
- @end
- //
- // Person.m
- //
- #import "Person.h"
- @implementation Person
- @dynamic age;
- @dynamic name;
- @end
6.おまじないコード
- //
- // MyCDataAppDelegate.h
- //
- #import <UIKit/UIKit.h>
- // ここ追加
- #import <CoreData/CoreData.h>
- @class MyCDataViewController;
- @interface MyCDataAppDelegate : NSObject <UIApplicationDelegate> {
- UIWindow *window;
- MyCDataViewController *viewController;
- // ここ追加
- @private
- NSManagedObjectContext *managedObjectContext_;
- NSManagedObjectModel *managedObjectModel_;
- NSPersistentStoreCoordinator *persistentStoreCoordinator_;
- }
- @property (nonatomic, retain) IBOutlet UIWindow *window;
- @property (nonatomic, retain) IBOutlet MyCDataViewController *viewController;
- // ここ追加
- @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
- @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
- @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- // ここ追加
- - (NSString *)applicationDocumentsDirectory;
- @end
- //
- // MyCDataAppDelegate.m
- //
- #import "MyCDataAppDelegate.h"
- #import "MyCDataViewController.h"
- @implementation MyCDataAppDelegate
- @synthesize window;
- @synthesize viewController;
- #pragma mark -
- #pragma mark Application lifecycle
- /**
- これ追加
- */
- - (void)awakeFromNib {
- viewController.managedObjectContext = self.managedObjectContext;
- }
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- [window addSubview:viewController.view];
- [window makeKeyAndVisible];
- return YES;
- }
- - (void)applicationWillResignActive:(UIApplication *)application {
- }
- - (void)applicationDidEnterBackground:(UIApplication *)application {
- }
- - (void)applicationWillEnterForeground:(UIApplication *)application {
- }
- - (void)applicationDidBecomeActive:(UIApplication *)application {
- }
- - (void)applicationWillTerminate:(UIApplication *)application {
- }
- #pragma mark -
- #pragma mark Memory management
- - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
- }
- - (void)dealloc {
- [viewController release];
- [window release];
- [super dealloc];
- }
- #pragma mark -
- #pragma mark Core Data stack
- /**
- これ追加(ゲッター)
- CoreData用に共通のContextを1つここで用意する。
- SQLiteファイルへの永続ストアコーディネータ(NSPersistentStoreCoordinator)のインスタンスを、用意したContextにセットする。
- */
- - (NSManagedObjectContext *)managedObjectContext {
- if (managedObjectContext_ != nil) {
- return managedObjectContext_;
- }
- NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
- if (coordinator != nil) {
- managedObjectContext_ = [[NSManagedObjectContext alloc] init];
- [managedObjectContext_ setPersistentStoreCoordinator:coordinator];
- }
- return managedObjectContext_;
- }
- /**
- これ追加(ゲッター)
- .xcdatamodeld (.xcdatamodelを内包した)バンドルを指定する。
- 管理オブジェクトモデル(NSManagedObjectModel)の準備をする。
- この管理オブジェクトモデルを使うことで、管理オブジェクト(アプリ側)とレコード(データベース側)とのマッピングさせる。
- */
- - (NSManagedObjectModel *)managedObjectModel {
- if (managedObjectModel_ != nil) {
- return managedObjectModel_;
- }
- NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"MyCData" ofType:@"momd"];
- NSLog(@"データモデルのバンドルディレクトリ(?)のパス %@", modelPath);
- NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
- managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
- return managedObjectModel_;
- }
- /**
- これ追加(ゲッター)
- 永続ストアとしてSQLite(ファイル)を指定する。
- この永続ストアコーディネータを使うことで、管理オブジェクトモデル(.xcdatamodel)と永続ストアを関連付けて管理できるようになる。
- */
- - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
- if (persistentStoreCoordinator_ != nil) {
- return persistentStoreCoordinator_;
- }
- NSURL *storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"MyCData.sqlite"]];
- NSError *error = nil;
- persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
- if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
- NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
- abort();
- }
- return persistentStoreCoordinator_;
- }
- #pragma mark -
- #pragma mark Application's Documents directory
- /**
- これ追加
- Returns the path to the application's Documents directory.
- */
- - (NSString *)applicationDocumentsDirectory {
- return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
- }
- @end
7.後は普通にコード書く
8.データの読み込みや追加などは、用意したコンテクスト(NSManagedObjectContext)を通じて実行
- //
- // MyCDataViewController.h
- //
- #import <UIKit/UIKit.h>
- // ここ追加
- #import <CoreData/CoreData.h>
- @interface MyCDataViewController : UIViewController {
- // ここ追加
- NSFetchedResultsController *fetchedResultsController_;
- NSManagedObjectContext *managedObjectContext_;
- // ここ追加
- IBOutlet UIButton *addButton;
- IBOutlet UIButton *requestButton;
- NSMutableArray *persons;
- }
- // ここ追加
- @property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
- @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
- // ここ追加
- @property (nonatomic, retain) IBOutlet UIButton *addButton;
- @property (nonatomic, retain) IBOutlet UIButton *requestButton;
- @property (nonatomic, retain) NSMutableArray *persons;
- - (IBAction)addPerson:(id)sender;
- - (IBAction)requestPersons:(id)sender;
- @end
- //
- // MyCDataViewController.m
- //
- #import "MyCDataViewController.h"
- // ここ追加
- #import "Person.h"
- @implementation MyCDataViewController
- // ここ追加
- @synthesize fetchedResultsController = fetchedResultsController_;
- @synthesize managedObjectContext = managedObjectContext_;
- @synthesize addButton;
- @synthesize requestButton;
- @synthesize persons;
- - (void)didReceiveMemoryWarning {
- [super didReceiveMemoryWarning];
- }
- - (void)viewDidUnload {
- // ここ追加
- self.addButton = nil;
- self.requestButton = nil;
- }
- - (void)dealloc {
- // ここ追加
- [addButton release];
- [requestButton release];
- [persons release];
- // ここ追加
- [fetchedResultsController_ release];
- [managedObjectContext_ release];
- [super dealloc];
- }
- /**
- これ追加
- */
- - (IBAction)addPerson:(id)sender
- {
- NSLog(@"- (IBAction)addPerson:(id)sender");
- NSManagedObjectContext *context = self.managedObjectContext;
- Person *person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
- [person setAge:[NSNumber numberWithInt:37]];
- [person setName:@"Jack"];
- NSError *error;
- if (![context save:&error]) {
- NSLog(@"Error");
- }
- }
- /**
- これ追加
- */
- - (IBAction)requestPersons:(id)sender
- {
- NSLog(@"- (IBAction)requestPersons:(id)sender");
- NSManagedObjectContext *context = self.managedObjectContext;
- NSFetchRequest *request = [[NSFetchRequest alloc] init];
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
- [request setEntity:entity];
- // ソート
- NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
- NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
- [request setSortDescriptors:sortDescriptors];
- [sortDescriptor release];
- [sortDescriptors release];
- NSError *error;
- NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];
- if (mutableFetchResults == nil) {
- NSLog(@"no results");
- }
- [self setPersons:mutableFetchResults];
- [mutableFetchResults release];
- [request release];
- for (Person *person in persons) {
- NSLog(@"%@", [person name]);
- }
- }
- @end
後このサンプルでは、InterfaceBuilderでMyCDataViewController.xibにボタン2つ追加してそれぞれIBOutletとIBActionを繋げれば動くはず。
0 件のコメント:
コメントを投稿