1

私はこれについて頭を悩ませているところにいるので、スレッドとコアデータで目的の C を使用した経験があるここの偉大な頭脳に手を差し伸べようと考えました。メイン スレッドからアクセスされる NSPrivateQueue コンテキストのスレッドに挿入されたマネージド オブジェクトに問題があります。大まかに言えば、私は AFNetworking を使用してスレッドを生成し、サーバーから JSON データを取得するリクエストを作成してから、永続ストアのコア データに値を挿入しています。これが完了したら、AFNetworking を使用してバイナリ データをダウンロードするための別のスレッドもあります。以下に示すように、このために 2 つのマネージド コンテキストを設定しました。

(NSManagedObjectContext *)masterManagedContext {
if (_masterManagedContext != nil) {
    return _masterManagedContext;
}

NSPersistentStoreCoordinator *coord = [self coordinator];
if (coord != nil) {
    _masterManagedContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
     _masterManagedContext.stalenessInterval = 0.0;
    [_masterManagedContext performBlockAndWait:^{
        [_masterManagedContext setPersistentStoreCoordinator:coord];
    }];

}
return _masterManagedContext;
}


// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)backgroundManagedContext {
if (_backgroundManagedContext != nil) {
 return _backgroundManagedContext;
 }

NSManagedObjectContext *masterContext = [self masterManagedContext];
if (masterContext != nil) {
    _backgroundManagedContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
     _backgroundManagedContext.stalenessInterval = 0.0;
    [_backgroundManagedContext performBlockAndWait:^{
        [_backgroundManagedContext setParentContext:masterContext];
    }];
}

return _backgroundManagedContext;

}

上記のように、子コンテキストと親コンテキストを使用しています。json データを取得するために呼び出すと、次のようなものがあります。

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        //Initially delete all records in table. This will change
         [[Singleton sharedInstance]removeEntityObjects:className];

           for (int x=0; x < [JSON count]; x++) {
                NSMutableDictionary *curDict = [JSON objectAtIndex:x];
                   [[CoreDatam sharedinstance] insertEmployeesWithDictionary:curDict];

                }else  {
                    /* do nothing */
                }
            }
        }

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error,id JSON) {

        [delegate performSelector:@selector(didNotCompleteSync:) withObject:className];
    }];

    [operations addObject:operation];
}    

[self.AFClient enqueueBatchOfHTTPRequestOperations:operations progressBlock:^(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations) {
    NSLog(@"Currenlty downloaded table data %d of %d!",numberOfCompletedOperations,totalNumberOfOperations);

} completionBlock:^(NSArray *operations) {

    if (_syncInProgress) {
          [[CoreDatam sharedInstance]updateEmpForId];



           [self downloadAllFiles];
    }
}];

}`

挿入機能については、次のようなものがあります。

 insertEmployeesWithDictionary:curDict {

[[self backgroundManagedContext]performBlockAndWait:^{
Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee"
                                                     inManagedObjectContext:[self backgroundManagedContext]];

/* Issues saving null into core data based on type.*/
[emp setFirst:[dictCopy objectForKey:@"first"]];
[emp setLast:[dictCopy objectForKey:@"last"]];


    NSError *error = nil;
    BOOL saved;
    saved = [[self backgroundManagedContext] save:&error];
    if (!saved) {
        NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }

    [self saveMasterContext];

}];

}

問題は、上記の完了ブロックにあるメソッドで管理対象オブジェクトにアクセスしようとしているところです。

updateEmpId {
[self.backgroundManagedContext performBlockAndWait:^{
     NSError *error = nil;
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Employee"];
    [request setSortDescriptors:[NSArray arrayWithObject:
                                 [NSSortDescriptor sortDescriptorWithKey:@"last" ascending:YES]]];

    myEmps = [self.backgroundManagedContext executeFetchRequest:request error:nil];

 for (Employee *moEmp in myEmps) {
        [[self backgroundManagedContext]refreshObject:moEmp mergeChanges:YES];
        moEmp.photo = @'default.pic';
 }
                NSError *saveError = nil;
                if (![self.backgroundManagedContext save:&saveError]) {
                NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
                }

            [self saveMasterContext];

}

問題は、メイン スレッドで変更された管理対象オブジェクトを見ると、非常に一貫性のない動作になることです。親子コンテキスト関係を使用する場合、管理された objectIds を渡す必要はありますか? もしそうなら、どうすれば上記の例でそうすることができますか? どんな助けでも大歓迎です。

4

1 に答える 1

1

ええ、メインスレッドのコンテキストで渡すNSManagedObjectIDsか、再取得する必要があります。オブジェクト ID を渡す場合は、新しい Employee オブジェクトを保存した後にバックグラウンド コンテキストから ID を取得existingObjectWithID:error:し、親コンテキストで使用してインスタンス化します。またはupdateEmpIdmasterManagedContext.

于 2013-03-05T02:22:01.000 に答える