English 中文(简体)
NSFedessedResults 主计长/有多重线索问题的核心数据
原标题:NSFetchedResultsController / CoreData with multiple threads issue

目前我正在开发一个使用CoreData 和 NSFectchedResults 控制器的应用程序。 此应用程序仅包含一个使用 NSFedResults 控制器的 UIT View 。

启动应用程序时, 另一个线条被分离。 在这个新线条中, 一个 WS 调用许可从网络服务器获取数据。 WS 调用后, 我将数据存储在 CoreData DB 中, 并存到另一个NSManageedObjectCortext (Apple the practice: another dress {gt; 另外一个上下文) 。 在保存新对象之前, 我不得不删除此实体的所有对象 。 我通过合并 CchangesFrom ContextedSave notification 将此其它上下文与主上下文合并 。

        // Data Manager (in another thread)
        NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
        [[NSNotificationCenter defaultCenter]   addObserver:self
                                                selector:@selector(contextDidSave:)
                                                name:NSManagedObjectContextDidSaveNotification
                                                object:context];
        [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
        [context setPersistentStoreCoordinator:[self getPersistentStoreCoordinator]];

        ...

        for (NSManagedObject * obj in objects) 
        {
            [context deleteObject:obj];
        }

        ...

        for(NSDictionary *serverObj in serverObjects)
        {
            objAd =  [NSEntityDescription
                      insertNewObjectForEntityForName:@"MyEntity" 
                      inManagedObjectContext:context];
            ...
        }

        [context save:&error];

        [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:context];
        [context release];

        ...

        - (void)contextDidSave:(NSNotification *)notification
        {

            SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
            [[self getContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES];
        }

        - (NSManagedObjectContext *) getContext
        {
            return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
        }

        - (NSPersistentStoreCoordinator *) getPersistentStoreCoordinator
        {
            return [(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
        }

<% 2> 这是我的NSFectchedResults 主计长的抓手:

        // UIView
    - (NSFetchedResultsController*) offersFRC {

        if (offersFRC == nil) 
        {
            NSManagedObjectContext *l_ManagedObjectContext = [[DataManager sharedDataManager] getContext];

            NSFetchRequest *l_FetchRequest = [[NSFetchRequest alloc] init];

            NSEntityDescription *l_Entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:l_ManagedObjectContext];
            [l_FetchRequest setEntity:l_Entity];

            [l_FetchRequest setFetchBatchSize:5];

            NSNumber *sortType = [self.searchCriterions objectForKey:@"sortType"];
            NSSortDescriptor *l_SortDescriptor = [[NSSortDescriptor alloc] initWithKey:[Constants getFieldNameBySortType:sortType] ascending:[Constants isAscendingBySortType:sortType]];
            [l_FetchRequest setSortDescriptors:[NSArray arrayWithObjects:l_SortDescriptor, nil]];
            [l_SortDescriptor release];

            NSFetchedResultsController *l_FetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:l_FetchRequest                                                                                                      managedObjectContext:l_ManagedObjectContext 
                sectionNameKeyPath:nil                                                                                                     
                cacheName:nil];
            [l_FetchRequest release];

            [self setOffersFRC:l_FetchedResultsController];
            [l_FetchedResultsController release],l_FetchedResultsController = nil;

            [self.offersFRC setDelegate:self];
        }

        return offersFRC;
    }

<% 1 > 3/ 应用程序启动时,我遇到以下错误 :

        2012-02-29 11:56:09.119 Nanopost[1996:207] *** Terminating app due to uncaught exception       NSObjectInaccessibleException , reason:  CoreData could not fulfill a fault for  0x5c3c760 <x-coredata://E176B0A1-275B-4332-9231-49FD88238C2B/Ads/p231>  
    *** Call stack at first throw:
    (
    0   CoreFoundation                      0x02bfe919 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x02e595de objc_exception_throw + 47
    2   CoreData                            0x028b833f _PFFaultHandlerLookupRow + 1407
    3   CoreData                            0x028b5ee3 _PF_FulfillDeferredFault + 499
    4   CoreData                            0x028b9f3f _sharedIMPL_pvfk_core + 95
    5   CoreData                            0x0292a010 _PF_Handler_Public_GetProperty + 160
    6   Foundation                          0x02442c4f -[NSSortDescriptor compareObject:toObject:] + 128
    7   CoreData                            0x0297db5e +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 286
    8   CoreData                            0x0297e1b2 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 402
    9   CoreData                            0x029841bc -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 1804
    10  Foundation                          0x02380c1d _nsnote_callback + 145
    11  CoreFoundation                      0x02bd6cf9 __CFXNotificationPost_old + 745
    12  CoreFoundation                      0x02b5611a _CFXNotificationPostNotification + 186
    13  Foundation                          0x023767c2 -[NSNotificationCenter postNotificationName:object:userInfo:] + 134
    14  CoreData                            0x028c0519 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 89
    15  CoreData                            0x028f802b -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 1579
    16  Foundation                          0x02395e9a __NSThreadPerformPerform + 251
    17  CoreFoundation                      0x02bdfd7f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    18  CoreFoundation                      0x02b3e2cb __CFRunLoopDoSources0 + 571
    19  CoreFoundation                      0x02b3d7c6 __CFRunLoopRun + 470
    20  CoreFoundation                      0x02b3d280 CFRunLoopRunSpecific + 208
    21  CoreFoundation                      0x02b3d1a1 CFRunLoopRunInMode + 97
    22  GraphicsServices                    0x031e62c8 GSEventRunModal + 217
    23  GraphicsServices                    0x031e638d GSEventRun + 115
    24  UIKit                               0x0063cb58 UIApplicationMain + 1160
    25  Nanopost                            0x0000230a main + 170
    26  Nanopost                            0x00002255 start + 53
    )
    terminate called after throwing an instance of  _NSCoreDataException 

<强度 > 进口说明 :

  • It crashes only on iOS4
  • controllerWillChangeContent is the last function called in my code before application s crash. controllerDidChangeContent / didChangeObject/ didChangeSection are not called.
  • When I comment [l_FetchRequest setFetchBatchSize:5] => No more crashes
  • When I add a [context save:&error] after objects deletion and before new objects insertion => No more crashes
  • When I use [l_FetchRequest setFetchBatchSize:24] => Crashes
  • When I use [l_FetchRequest setFetchBatchSize:25] => No more crashes

我花了很多时间试图理解这个问题,

托马斯·托马斯

Edit 1 (@Jody): Hi Jody and thank you very much for your answers!

以下是用于处理上下文的代码 是否保存 :

    - (void)contextDidSave:(NSNotification *)notification
    {
        SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); 
        [[self getContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES];
    }

"你必须先告诉我更多关于你使用的上下文":

我在此应用程序中使用了 2 个上下文 :

  • N° 1 : 在创建 XCode Project 时默认创建于 AppDelegate 中。 此上下文被我的 FRC 使用, 并允许显示 UITView 的行 。

  • 第2点:在我的“数据管理器”(我的文章中的第一个代码块)中创建,一个允许刷新我的DB(WS呼叫、删除、重新插入、保存)的单吨。

当保存了第2号上下文时, 上下文Save 被调用将上下文与主上下文( 文本编号 1: ) 合并为上下文 。 在此之后, 我的 FRC 代表方法“ 控制器 Will Change Content ” 被调用 。 我不认为它有助于显示此方法所含的代码, 因为即使我刚刚放了一个NSLog, 它也随此方法而崩溃( 我将许多 NSLog 和 NSLog 包含在控制器 WillChange Content 中的 NSLog 是崩溃前显示的最后一个 ) 。

我已经在苹果Dev论坛上张贴了一个有趣的答案:

问题回答

您正在以一个上下文从数据库中删除, 所以您必须适当刷新您的其他上下文, 并具体地说, 将您对象的引用删除到被删除的数据 。

您的处理框架DidenSave: 的代码是什么? 另外, 您的 FRC 代表对数据更新通知做什么?

<强 > EDIT

看起来您正在混合管理对象的上下文。 您正在使用数据管理器中的一个来装入和修改数据库...

// Data Manager (in another thread)
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];

然后用“默认” MOC 来通过通知将数据拖入您的应用程序, 但它看起来就像您所获取的结果控制器 也在试图从另一个线索中使用 MOC...

NSManagedObjectContext *l_ManagedObjectContext = [[DataManager sharedDataManager] getContext];

可能也该使用主控制控制器(来自您的应用程序代表),





相关问题
List Contents of Directory in a UITableView

I am trying to list the contents of Ringtones directory in a TableView, however, I am only getting the last file in the directory in ALL cells, instead of file per cell. This is my code: - (...

iPhone NSUserDefaults persistance difficulty

In my app i have a bunch of data i store in the NSUserdefaults. This information consists of an NSObject (Object1) with NSStrings and NSNumbers and also 2 instances of yet another object (Object2). ...

Writing a masked image to disk as a PNG file

Basically I m downloading images off of a webserver and then caching them to the disk, but before I do so I want to mask them. I m using the masking code everyone seems to point at which can be found ...

Resize UIImage with aspect ratio?

I m using this code to resize an image on the iPhone: CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0); UIGraphicsBeginImageContext(screenRect.size); [value drawInRect:screenRect blendMode:...

Allowing interaction with a UIView under another UIView

Is there a simple way of allowing interaction with a button in a UIView that lies under another UIView - where there are no actual objects from the top UIView on top of the button? For instance, ...