ページ

2010年2月4日木曜日

BlogAssistant(13) - Queueの導入: plistの読み込みと CoreDataへの保存

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Cocoaの日々: BlogAssistant(12) - Queueの導入: plistの保存

Safariプラグインで保存した plist を読み出し、CoreDataへ保存する実装を管理アプリで行う。

まず QueueManager を作った。ここで plist の読み込みから CoreDataへの保存までのコントロールを行う。
QueueManager.m

- (void)loadFiles
{
 NSFileManager* fm = [NSFileManager defaultManager];
 NSString* path = [[PathManager sharedManager] queuePath];
 NSError* error = nil;

 NSArray* files = [fm contentsOfDirectoryAtPath:path
     error:&error];
 if (error) {
  NSLog(@"ERROR(loadFiles): %@", error);
  return;
 }
 ModelManager* mm = [ModelManager sharedManager];
 for (NSString* filename in files) {
  if ([[filename pathExtension] isEqualToString:@"plist"]) {
   ResourceTransfer* resTran =
    [ResourceTransfer resourceTransferWithContentsOfFile:filename];
   if (resTran) {
    [mm insertResourceWithTransfer:resTran];
   }
  }
 }
}

まず所定のフォルダ(Queue)内の plist ファイルの一覧を作る。次に plist 毎に ResourceTransfer を作成する。そしてそれを ModelManager に渡して CoreData へ保存する。

plist から ResourceTransfer を作るメソッドはこんな感じ。

ResourceTransfer.m
+ (ResourceTransfer*)resourceTransferWithContentsOfFile:(NSString*)filename
{
 return [[[ResourceTransfer alloc] initWithContentsOfFile:filename] autorelease];
}
- (id)initWithContentsOfFile:(NSString*)filename
{
 self = [super init];
 if (self) {
  NSString* path = [[[PathManager sharedManager] queuePath] stringByAppendingPathComponent:filename];
  NSDictionary* inputDict = [NSDictionary dictionaryWithContentsOfFile:path];
  if (inputDict) {
   for (NSString* key in [inputDict allKeys]) {
    [self setValue:[inputDict valueForKey:key] forKey:key];
   }
  }
 }
 return self;
}


CoreDataへの保存は -[ModelManager insertResourceWithTransfer:] で行う。

ModelManager.m
-(BOOL)insertResourceWithTransfer:(ResourceTransfer*)resTran
{
 NSManagedObjectContext* moc = [[CoreDataManager sharedManager] managedObjectContext];

 Resource* resource =
 (Resource*)[NSEntityDescription insertNewObjectForEntityForName:@"Resource"
            inManagedObjectContext:moc];

 NSArray* keys = [Utility getPropertyNamesOf:resTran];
 for (NSString* key in keys) {
  [resource setValue:[resTran valueForKey:key] forKey:key];
 }
 NSError* error = nil;
 
 [moc save:&error];
 
 if (error) {
  NSLog(@"ERROR(insertResourceWithTransfer:): %@", error);
  return NO;
 }
 
 return YES;
}

+[Utility getPropertyNamesOf:] は以前紹介した class_copyPropertyList( ) を使ってプロパティ一覧を取得するユーティリティ。前回も ResourceTransfer 内で使っていたがリファクタリングして Utilityクラスへ移した。

Utility.m
+ (NSArray*)getPropertyNamesOf:(id)object
{
 NSMutableArray* propertyNames = [NSMutableArray array];

 unsigned int outCount, i;
 objc_property_t *properties =
 class_copyPropertyList([object class], &outCount);
 
 for(i = 0; i < outCount; i++) {
  objc_property_t property = properties[i];
  NSString *propertyName =
  [NSString stringWithUTF8String:property_getName(property)];
  [propertyNames addObject:propertyName];
 }
 free(properties);
 
 return propertyNames;
}

クラスの依存関係はこんな感じ。

ResourceTransfer と Resource の間の依存関係は無い。この間の依存関係を知っているのは ModelManager だけ。


実行してみよう。Safariでクリップしておき、管理アプリ側で -[QueueManager loadFiles] を呼び出す。

表示された。動いているようだ。


ソースコード(GitHub)
xcatsan's BlogAssistant at 2010-02-04 - GitHub