현재 CoreData와 NSFectchedResultsController를 사용하는 응용 프로그램을 개발 중입니다. 이 응용 프로그램은 NSFetchedResultsController를 사용하는 하나의 UITableView 만 포함합니다.NSFetchedResultsController/CoreData with multiple threads issue
1/ 응용 프로그램이 시작되면 다른 스레드가 분리됩니다. 이 새로운 스레드에서 WS 호출은 웹 서버에서 데이터를 검색하도록 허용합니다. WS 호출 후 다른 NSManagedObjectContext (다른 스레드 => 다른 컨텍스트)와 함께 CoreData DB에 데이터를 저장합니다. 새로운 개체를 저장하기 전에이 개체의 모든 개체를 삭제해야합니다. mergeChangesFromContextDidSaveNotification을 통해이 컨텍스트를 주 컨텍스트와 병합합니다. 응용 프로그램이 실행될 때 다음과 같은 오류가있어
// 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;
}
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'
여기
2/
// 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];
}
내 NSFectchedResultsController의 게터입니다 메모 :
그것은 단지 iOS4에 충돌
- 는
- controllerWillChangeContent는 응용 프로그램의 충돌 전에 내 코드에서 마지막으로 호출 된 함수입니다. controllerDidChangeContent/didChangeObject/didChangeSection이 호출되지 않습니다.
- 내가 언급 [l_FetchRequest setFetchBatchSize : 5] => 더 이상 충돌하지
- 나는 [저장 컨텍스트 : & 오류] 추가 삽입 => 더 이상 충돌 개체를 삭제 한 후 새로운 객체 이전을
- 내가 사용하는 [25 l_FetchRequest setFetchBatchSize] => 더 이상 충돌
나는이 문제를 이해하려고 많은 시간을 보냈습니다 그래서 당신에게 매우 감사드립니다 내가 사용하는 경우 : [l_FetchRequest setFetchBatchSize 24] =이>
토마스
편집 1 (@Jody) : 안녕 조디와 귀하의 답변을 주셔서 대단히 감사합니다! 여기
는 contextDidSave을 처리하는 데 사용하는 코드입니다 :- (void)contextDidSave:(NSNotification *)notification
{
SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
[[self getContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES];
}
"먼저 나에게 당신이 사용하고있는 상황에 대한 자세한 얘기를 해"
나는이 응용 프로그램에서이 컨텍스트를 사용
를N ° 1 : XCodeProject를 만들 때 AppDelegate에서 기본적으로 만들어집니다. 이 컨텍스트는 FRC에서 사용하며 UITableView의 행을 표시 할 수 있습니다.
N ° 2 : 내 DB (WS 호출, 삭제, 다시 삽입, 저장) 새로 고침을 허용하는 싱글 톤 인 "DataManager"(내 게시물의 첫 번째 코드 블록)에 작성되었습니다.
컨텍스트 번호 2가 저장되면이 컨텍스트를 주 컨텍스트 (컨텍스트 N ° 1)와 병합하기 위해 contextDidSave가 호출됩니다. 그 후, 내 FRC 대리인의 메서드 "controllerWillChangeContent"가 호출됩니다. 나는이 메소드에 포함 된 코드를 표시하는 데 도움이되지 않을 것이라고 생각한다. NSLog를 넣었을지라도이 메소드 (NSLog를 많이 넣었고 controllerWillChangeContent에 포함 된 NSLog가 전에 표시되는 마지막 값이다. 충돌).
나는 애플 개발자 포럼에 게시하고 흥미로운 응답이 : https://devforums.apple.com/thread/152172?tstart=0
편집 2 (@Jody) : 안녕 조디!
다음과 같은 방법에서 볼 수 있듯이, 내 FRC는 다른 스레드에서 MOC를 사용하지 않습니다
- (NSManagedObjectContext *) getContext
{
return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
내 "DataManager에"이 방법은 AppDelegate에의 MOC (= 메인 스레드의 MOC)를 반환
서식에 형식이 없으므로 주석에 코드를 넣지 마십시오. 또한 더 나은 질문을 제공하기 위해 질문을 편집하는 것이 좋습니다. 코드에 관해서는, DidSave 핸들링을 다루기 전에 먼저 사용중인 컨텍스트에 대해 더 자세히 말해야합니다 ... 다시 어디에서 왔는지? 어떻게 만들어 졌습니까? MR 문맥과의 관계는 무엇입니까? –
죄송합니다. 같은 질문이지만 MR 파트를 무시합니다 (Hardees의 도로에서 응답). 다른 질문과 섞였습니다. 혼동을해서 죄송합니다. –
Jody에게 감사드립니다! 내 질문을 편집했습니다! –