0

В настоящее время у меня есть проблема с threading с управляемым объектом в моем приложении. В настоящее время у меня есть фоновый поток, который ДОЛЖЕН быть в фоновом режиме, но одновременно получает доступ к управляемому объекту. Другой ViewController вызывает метод processAllApplications, показанный ниже, который затем вызывает checkCompletedApplicationsFor24HourExpiration, который затем вызывает getAppsWithStatus. Кажется, что в настоящее время поток заблокирован, и эта операция останавливается там, где указано предупреждение. Мне нужен способ обработать это, и я достаточно нул, когда дело доходит до Core Data. Кто-нибудь сможет посоветовать. Я читал, что мне, возможно, придется создавать несколько экземпляров моего управляемого объекта и объединять их. Как я могу это сделать, если это так?NSManagedObjectContext сбой при обращении к внешнему потоку

AppDelegate:

- (NSManagedObjectContext *)managedObjectContext 
{ 

    [__managedObjectContext lock]; 
    if (__managedObjectContext != nil) { 

     [__managedObjectContext unlock]; 
     return __managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     __managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [__managedObjectContext setPersistentStoreCoordinator:coordinator]; 
    } 

    [__managedObjectContext unlock]; 
    return __managedObjectContext; 

} 
    - (NSMutableArray*)getAppsWithStatus:(int)intStatus { 


    NSLog(@"%i on main thread getAppsWithStatus", [NSThread currentThread].isMainThread); 
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Application" inManagedObjectContext:self.managedObjectContext]; 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setEntity:entityDescription]; 

    // Set example predicate and sort orderings... 
    NSNumber *status = [NSNumber numberWithInt:intStatus]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %@ && username = %@", status, [[NSUserDefaults standardUserDefaults] objectForKey:@"username"]]; 
    #warning FAILS HERE INTO ABYSS 
    [request setPredicate:predicate]; 

    NSError *error = nil; 

    NSMutableArray* applications = [[NSMutableArray alloc] initWithArray:[self.managedObjectContext executeFetchRequest:request error:&error]]; 
    for (Application* eachApp in applications) 
     eachApp.applicationNumber = nil; 
    [self saveDB]; 
    return applications; 
} 

    - (void)processAllApplications:(id)userInfo { 
    [self.processApplicationsLock lock]; 

    if ([[NSUserDefaults standardUserDefaults] objectForKey:@"username"] == nil) return; // Not logged in 
    NSLog(@"processing"); 
    [self checkCompletedApplicationsFor24HourExpiration]; 
    [self alertFor12HourCompletedApplications]; 
    [self alertForExpiredDraftApplications]; 

    if ([DeleteAllDraftApplicationsForCurrentApplicationYear isSatisifiedByDate:[DateTimeFactory currentApplicationDate]]) { 
     [self deleteExpiredApps]; 
    } 

    [self performSelector:@selector(sendApplications:) withObject:nil afterDelay:3]; 

    [self.processApplicationsLock unlock]; 
} 

- (void)checkCompletedApplicationsFor24HourExpiration { 

    NSLog(@"OutboxSender - (void)checkCompletedApplicationsFor24HourExpiration"); 
    NSLog(@"%i on main thread checkCompletedApplicationsFor24HourExpiration", [NSThread currentThread].isMainThread); 
    NSArray* completedApps = [self getAppsWithStatus:STATUS_COMPLETED]; 
    NSDate* targetDate = [self offsetDate:[DateTimeFactory currentApplicationDate] withDay:-1 withMonth:0 withHour:0]; 

    for (Application* theApplication in completedApps) { 
     if ([MoveCompletedApplicationToDraftApplicationSpec isSatisfiedByApplication:theApplication cutOffDate:targetDate]) { 
      NSLog(@"Sending To draft with date: %@", theApplication.submittedDate); 
      theApplication.status = [NSNumber numberWithInt:STATUS_DRAFT]; 
      [self deleteSignatures:theApplication]; 
     } 
    } 

    NSString* message = [NSString stringWithFormat:@"%i completed application/s have been sent to drafts", [completedApps count]]; 
    echo_Alert(@"", message); 

    [self saveDB]; 
} 

ответ

1
create separate managed object context 

+(NSManagedObjectContext *)getManagedObjectContext 
{ 
    NSManagedObjectContext *managedObjectContext; 
    @try { 
     NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator]; 
     if (coordinator != nil) { 
      managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
      [managedObjectContext setPersistentStoreCoordinator: coordinator]; 
     } 

    } 
    @catch (NSException *exception) { 
     NSLog(@"Exception occur %@",exception); 
    } 
    return managedObjectContext; 

Use this separate managed object context in your fetching method, 

    - (NSMutableArray*)getAppsWithStatus:(int)intStatus { 

NSMutableArray * mutableObjects; 
    NSLog(@"%i on main thread getAppsWithStatus", [NSThread currentThread].isMainThread); 
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Application" inManagedObjectContext:[self getManagedObjectContext]]; // Here use separate managed object context 
    NSFetchRequest *request = [[NSFetchRequest alloc] init]; 
    [request setEntity:entityDescription]; 

    // Set example predicate and sort orderings... 
    NSNumber *status = [NSNumber numberWithInt:intStatus]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = %@ && username = %@", status, [[NSUserDefaults standardUserDefaults] objectForKey:@"username"]]; 
    #warning FAILS HERE INTO ABYSS 
    [request setPredicate:predicate]; 

    NSError *error = nil; 

    NSMutableArray* applications = [[NSMutableArray alloc] initWithArray:[[self getManagedObjectContext] executeFetchRequest:request error:&error]]; 

NSMutableArray * resultedArray = [applications mutableCopy]; 
     NSMutableArray * objectIds = [[NSMutableArray alloc] initWithCapacity:[resultedArray count]]; 
     for (NSManagedObject *obj in resultedArray) { 
      [objectIds addObject:obj.objectID]; 
     } 

     mutableObjects = [[NSMutableArray alloc] initWithCapacity:[objectIds count]]; 
     for (NSManagedObjectID * objectID in objectIds) { 
      NSManagedObject * obj = [self.managedObjectContext 
objectWithID:objectID]; // Here use self.managedObjectContext in which you already created. 
      [mutableObjects addObject:obj]; 
     } 

    for (Application* eachApp in mutableObjects) 
     eachApp.applicationNumber = nil; 
    [self saveDB]; 
    return mutableObjects; 
} 
+0

Ну, это вызвало безумный побочный эффект экрана мигающим o.o. Для этого мне нужно будет изучить это. Вероятно, UIAlert работает на обратной линии ... – TheCodingArt

+0

Еще раз спасибо за ответ, если вы знаете какие-либо ресурсы, которые я мог бы изучить (помимо документации на ядро), которая отмечает этот тип параллелизма с Core Data в потоках, это было бы замечательно Помогите. Все биты информации очень ценятся. – TheCodingArt

Смежные вопросы