2

CoreDataのインポートを処理するNSOperationsサブクラスがいくつかあります。メインスレッド以外の問題のほとんどにチェックを入れたと思います

  • mainメソッドで独自の自動解放プールを作成します
  • NSManagedObjectContext操作ごとにを作成します

これらの操作はNSOperationQueueにロードされ、同時操作の最大数は1に設定されます。

コードはiOS4.0.1で完全に機能しますが、iOS 3.1.3デバイスでは、次のような多くのログメッセージが表示されます

*** _NSAutoreleaseNoPool(): Object 0x5f926c0 of class NSCFDictionary autoreleased with no pool in place - just leaking

NSOperationサブクラスのメインメソッド

-(void) main{

    NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];

    @try {
    //Start Operation
    //====================================
    NSManagedObjectID       *objID      = nil;
    NSError             *err        = nil;
    id                              user            = nil;

    if( !(userID = [self __lookup:[self userID] inContext: [self threadContext]]) ){

        //Set the name of the element
        user = [[self threadContext] objectWithID:objID];
        //Update the name
        [user setValue:@"John Doe"  forKey:@"name"];
        [user setValue:@"Hello world" forKey:@"status"];
    }


    if( ![[self threadContext] save:&err] ){
        DebugLog(@"Couldn't savechanges %@", err);
    }

    //====================================
    //End Operation
    }
    @catch (NSException * e) {
        DebugLog(@"Exception %@",e);
    }
    //====================================


   [pool drain];
}

__lookup:inContext:方法_

-(NSManagedObjectID*) __lookup:(id)aID inContext:(NSManagedObjectContext*) aContext{

    NSPredicate             *predicate      = nil;
    NSEntityDescription     *entity;
    NSFetchRequest          *fetchRequest   = nil;
    NSError                 *err            = nil;

    predicate = [NSPredicate predicateWithFormat:@"userID == %@",aID];

    entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:aContext];

    fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

    [fetchRequest setPredicate:predicate];

    [fetchRequest setEntity:entity];

    //Only fetch id's for speed
    [fetchRequest setResultType:NSManagedObjectIDResultType];

    return [[aContext executeFetchRequest:fetchRequest error:&err] lastObject];

}

他のほとんどのメソッドはメソッドをインスタンス化します。つまりthreadContext、メソッドに似てい__lookup:inContext:ます。インスタンスメソッドの自動解放プールを作成しないことは知っていますが、自動解放がどのように機能するかについての私の理解によれば、これらのメソッドがメインメソッド内でのみ呼び出される限り、NSAutoreleasePool作成された後、最も外側のプール使用すべきです。NSManagedObjectContextなどのオブジェクトを怠惰に作成し、ほとんどの場合、startメソッドを使用しません

4

1 に答える 1

0

解決しました。この操作は、Dave Dribinの記事のアドバイスを使用して NSURLConnection を起動していました。ただし、可能な限り、他の人のコードをカット アンド ペーストしないようにしています。そのため、自分のコードに入れているものを常にフィルター処理できます。

このチェックを追加するのを忘れていたことが判明しました

if( ![NSThread isMainThread] ){
    [self performSelectorOnMainThread:@selector(start) 
                           withObject:nil 
                        waitUntilDone:NO];
    return;
}

これにより、がすでに存在するstartメイン スレッドでメソッドが実行されるようになります。NSAutoreleasePool単純な間違い、簡単な解決策。

于 2010-11-10T19:40:35.540 に答える