Neuer Thread + NSManagedObjectContext
Ich versuche, meine Anwendungsarbeit zu trennen, wenn eine größere Arbeit zur Leistungsoptimierung erforderlich ist. Mein Problem ist über aNSManagedObjectContext
wird in einem anderen Thread als dem Haupt-Thread verwendet.
Ich rufe an:
[NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:myObject];
Auf dertest
Methode gibt es einige Dinge zu tun und ich habe ein Problem hier:
NSArray *fetchResults = [moc
executeFetchRequest:request
error:&error];
Hier ist meintest
Methode:
-(void) test:(MyObject *)myObject{
@autoreleasepool {
//Mycode
}
}
Daszweite Mal rufe ich die antest
Methode, mein neuer Thread wird blockiert, wenn dieexecuteFetchRequest
wird genannt. Dieses Problem ist bei mir angekommentest
Methode wird mehrmals hintereinander aufgerufen. Ich denke das Problem kommt von dermoc
aber ich kann nicht wirklich verstehen warum.
Bearbeiten:
Mit @ Charlies Methode funktioniert es fast. Hier ist mein Code zum Speichern meinerNSManagedObjectContext
(Objekt in meinem neuen Thread erstellt).
- (void) saveContext:(NSManagedObjectContext *) moc{
NSError *error = nil;
if ([moc hasChanges] && ![moc save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
}
Diese Methode wird für den neuen Thread aufgerufen. Mein Problem ist jetzt, dass ich mit diesem Save einen Deadlock habe und nicht wirklich verstehe, warum. Ohne es funktioniert perfekt.
Edit2
Ich arbeite an diesem Problem, kann es aber immer noch nicht beheben. Ich habe meinen Code über das geändertdetachNewThreadSelector
. Hier ist mein neuer Code:
NSManagedObjectContext* context = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
context.persistentStoreCoordinator = self.persistentStoreCoordinator;
context.undoManager = nil;
[context performBlock:^
{
CCImages* cachedImage;
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
childContext.parentContext = context;
cachedImage=[CCImages getCCImageForKey:path inManagedObjectContext:childContext];
UIImage *image = [self getImageFromCacheWithPath:path andCachedImage:cachedImage atDate:now];
if (image != nil){
if(![weakSelf.delegate respondsToSelector:@selector(CacheCacheDidLoadImageFromCache:)])
[weakSelf setDelegate:appDelegate.callbacksCollector];
//[weakSelf useCallbackCollectorForDelegate:weakSelf inMethod:@"initPaginatorForListMoments"];
[weakSelf.delegate CacheCacheDidLoadImageFromCache:image];
}
}
- (UIImage*) getImageFromCacheWithPath:(NSString*) path andCachedImage:(CCImages *) cachedImage atDate: (NSDate *) now{
NSURL* localURL=[NSURL URLWithString:cachedImage.path relativeToURL:[self imageCacheDirectory]];
UIImage * image;
//restore uiimage from local file system
if (localURL) {
image=[UIImage imageWithContentsOfFile:[localURL path]];
//update cache
[cachedImage setLastAccessedAt:now];
[self saveContext];
if(image)
return image;
}
return nil;
}
Kurz danach speichere ich meine Kontexte (vorerst manuell)
[childContext performBlock:^{
NSError *error = nil;
if (![childContext save:&error]) {
DDLogError(@"Error during context saving when getting image from cache : %@",[error description]);
}
else{
[context performBlock:^{
NSError *error = nil;
if (![context save:&error]) {
DDLogError(@"Error during context saving when getting image from cache : %@",[error description]);
}
}];
}
}];
Es gibt ein merkwürdiges Problem. Meine Rückrufmethode wird auf meinem Controller (der das implementiert) problemlos aufgerufenCacheCacheDidLoadImageFromCache:
Methode). Auf dieser Methode bestätige ich den Empfang des Bildes (DDLogInfo) und sage, dass ich möchte, dass mein Spinner stoppt. Es erfolgt nicht direkt, sondern erst 15 Sekunden nach dem Aufruf der Callback-Methode.
Mein Hauptproblem ist, dass mein Kontext (ich vermute) immer noch mein Bild aus dem Cache lädt, während es bereits gefunden wurde. Ich sagte 'schon', weil die Rückrufmethode aufgerufen wurde und das Bild vorhanden war. Es liegt keine verdächtige Aktivität der CPU oder des Speichers vor. Instrumente haben kein Leck gefunden.
Ich bin mir ziemlich sicher, dass ich das falsch benutzeNSManagedObjectContext
aber ich kann nicht finden, wo.