1

이것은 매우 기괴한 문제이며 핵심 데이터를 이해한다고 생각했습니다.배경 변경 NSManagedObjectContext가 NSFetchedResultsController를 사용하여 Main에 표시되지 않습니다.

부모가없는 배경 컨텍스트를 사용합니다. 영구 저장소 코디네이터에 바로 연결됩니다. 이 배경 컨텍스트에서 개체를 업데이트 한 다음 저장합니다. ContextDidSaveNotification을 듣고 변경 사항을 주 스레드 컨텍스트에 병합합니다. 이러한 업데이트 된 객체는 이미 테이블 뷰 셀을 채우는 데 사용되었으므로 주 스레드의 오류가 아닙니다. 그래서 나는 그 변화가 실제로 병합 될 것으로 기대합니다. 그러나 그들은 그렇지 않습니다.

내 데이터 모델의 세부 사항에 익숙하지 않아도 객체의 속성이 "downloadState"이면 충분합니다. 구문 분석 작업이 백그라운드 스레드에서 수행되면 downloadStateValue (열거 형)은 "completed"에 해당하는 "3"으로 설정됩니다.

지금 어떤 일이 일어나고 있는지 확인하려면 ContentWillSave 알림에 가입하십시오. 내 분석 작업 끝에이 얻을 :

2016-06-13 10:19:21.055 MyApp[29162:52855206] Going to save background context. 
updated:{(
<QLUserPinnedCourse: 0x7fe195403c10> (entity: QLUserPinnedCourse; id: 0xd0000000002c0002 <x-coredata://95821ADC-8A1F-4DAC-B20C-EDD8F8F413EA/QLUserPinnedCourse/p11> ; data: { 
    course = "0xd000000000dc0008 <x-coredata://95821ADC-8A1F-4DAC-B20C-EDD8F8F413EA/QLCourse/p55>"; 
    courseId = 2794; 
    /* other fields redacted */ 
}), 
<QLCourse: 0x7fe1954cded0> (entity: QLCourse; id: 0xd000000000dc0008 <x-coredata://95821ADC-8A1F-4DAC-B20C-EDD8F8F413EA/QLCourse/p55> ; data: { 
/* other fields redacted*/ 
contentDownloadState = 3; 
courseId = 2794; 
pinnedUserData = "0xd0000000002c0002 <x-coredata://95821ADC-8A1F-4DAC-B20C-EDD8F8F413EA/QLUserPinnedCourse/p11>"; 
    }) 

listenting되는 NSFetchedResultsControllerQLUserPinnedCourse에 물체가 내 테이블에 세포를 다시로드를 트리거 delegate 전화를 가져옵니다.

술어이다 : 나는 셀 코드에 도착하면

// Specify criteria for filtering which objects to fetch 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"pinned == %@ && course.contentDownloadState IN %@", 
            @YES, 
            @[@(QLDownloadStateSucceeded), @(QLDownloadStateNotYetAttempted), @(QLDownloadStateFailed), @(QLDownloadStateIncomplete)] 
            ]; 

지금, 내가 작업 할 QLUserPinnedCourse 목적이있다. 내가 디버거에서 중단 점을 설정하고 얻을 :

(lldb) po userCourse.course 
<QLCourse: 0x7fe19568f740> (entity: QLCourse; id: 0xd000000000dc0008 <x-coredata://95821ADC-8A1F-4DAC-B20C-EDD8F8F413EA/QLCourse/p55> ; data: { 

    contentDownloadState = 1; 
    courseId = 2794; 
    pinnedUserData = "0xd0000000002c0002 <x-coredata://95821ADC-8A1F-4DAC-B20C-EDD8F8F413EA/QLUserPinnedCourse/p11>"; 
}) 

질문은 왜 contentDownloadState하지 3,하지만 여전히 1,입니까 ?? 나는 그것을 얻지 않는다.

이러한 변경 사항을 병합해서는 안됩니까? 내 스택으로

세부 사항 :

PSC -> Private Concurrent (saving context) -> Main Thread context 

PSC -> Private Concurrent (import context) 

ContextDidSave : 나는 userCourse 부탁 해요

_contextSaveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification 
                      object:nil 
                       queue:nil 
                     usingBlock:^(NSNotification* note) 
          { 
           NSManagedObjectContext *contextSaved = note.object; 
           NSManagedObjectContext *moc = weakself.mainQueueContext; 

           // basically, if this was a background worker thread 

           DDLogDebug(@"updatedObjects:%@", note.userInfo[NSUpdatedObjectsKey]); 

           if ([contextSaved.userInfo[CoreDataUserInfoKeyIsWorkerContext] boolValue]) 
           { 
            [weakself.privateSavingContext performBlock:^(){ 

             for (NSManagedObject *object in note.userInfo[NSUpdatedObjectsKey]) { 
              [[weakself.privateSavingContext objectWithID:[object objectID]] willAccessValueForKey:nil]; 
             } 

             [weakself.privateSavingContext mergeChangesFromContextDidSaveNotification:note]; 

             [moc performBlock:^(){ 

              for (NSManagedObject *object in note.userInfo[NSUpdatedObjectsKey]) { 
               [[moc objectWithID:[object objectID]] willAccessValueForKey:nil]; 
              } 

              [moc mergeChangesFromContextDidSaveNotification:note]; 


             }]; 
            }]; 
           } 
          }]; 

주 : 문맥 가져 오기 컨텍스트가 있다면, 위의 두 상황에 변경 내용을 병합 내 FRC는 QLUserPinnedCourse 개체에 관심이 있지만 해당 특성에 대한 .course 개체. 나는 QLCourse 오브젝트와 관련된 술어에 keypath를 지정했기 때문에 이러한 변경 사항이 새로 고쳐 졌다고 생각했습니다.

+0

다운로드 상태를 설정 한 코드를 표시 할 수 있습니까? – orkoden

+0

그것은 주 스레드 컨텍스트에서 performBlockAndWait : 호출 내에서 수행되었으며 PSC까지 저장하도록 지시합니다. 코드 자체는 내 핵심 데이터 컨트롤러에 대해 더 많이 알아야하기 때문에 유용하지 않습니다. 이 코드는 잘 작동하는 것으로 입증되었습니다. 또한, 그래서 의견에 fixedFont 마크 업을 허용해야합니다! 병합 정책 문제 일 수 있습니까? 작업자 컨텍스트를 만든 후에 MT에서 이러한 속성을 설정한다고 생각합니다. 그 작업자는 그 업데이트를 병합하지 않았습니다. – horseshoe7

답변

1

이것은 핵심 데이터의 단점입니다. 저장 작업에 의해 업데이트 된 주 컨텍스트의 객체를 실제로 다시 폴링해야합니다.

여기 스위프트의 예이다 :

mainContext.performBlock { 
    let updatedObjects : Set<NSManagedObject> = notification.userInfo![NSUpdatedObjectsKey] as! Set<NSManagedObject> 

    for obj in updatedObjects { 
     self.mainContext.objectWithID(obj.objectID).willAccessValueForKey(nil) 
    } 

    self.mainContext.mergeChangesFromContextDidSaveNotification(notification) 
} 

주요 부분 객체가 오류로 표시되도록 willAccessValueForKey:nil 호출이다. 주 컨텍스트에서 NSFetchedResultsController이 실행됩니다.

+0

은 내가 하나의 관계 인 대상을보고 있기 때문에 그 것입니까? 그래서 그것은 상쾌하게하지 않는다? NSFetchedResultsController는 "그것에 대해 신경 쓰지 않습니다"? – horseshoe7

+0

NSFetchedResultsController의 대리자 메서드가 실행되지 않습니다. QLCourse 유형의 관련 객체처럼 보이지 않는 것 같습니다. – horseshoe7

+1

관련 개체의 속성 변경에 대해 'NSFetchedResultsController'가 실행되지 않습니다. 관계 만 변경하면 변경이 시작됩니다. 내 자신의 코드에서 FRC가 강제로 실행되도록 관계를 설정합니다 (현재 값 (예 :'obj.relationship = obj.relationship ')). – Avi

1

그래서 해결책을 찾았지만 왜 작동하는지 말할 수 없습니다.

내가 '콘텐츠 다운로드를 시작하는'메서드를 가지고 있고 기본 스레드 컨텍스트에서 contentDownloadState 속성을 'incomplete/downloading'으로 업데이트 한 다음 모든 콘텐츠를 가져 오는 것으로 계속 진행할 것이라고 생각하는 문제가 있습니다.

나머지 모든 작업은 백그라운드 스레드 컨텍스트에서 수행되었습니다. 완료되면 해당 값을 '성공'으로 업데이트했습니다. 그 변화를 합병하지 않았습니다. 나는 이유를 모른다.

일단 작업자 컨텍스트에서 모든 작업을 수행하기로 결정했습니다. 즉 그 값을 변경하고 디스크에 컨텍스트를 저장하고, 변경 사항, 모든 변경 사항이 전파됩니다.

결국 나는 그것을 풀었지만 실제로는 그 문제를 이해하지 못합니다.