2012-09-26 2 views
4

교착 상태 문제를 해결하기 위해 IPOD 라이브러리에서 객체 인스턴스에 대한 참조는 CoreData를 통해 다시 저장됩니다. 여기에 관심있는 것은 정확히 무슨 일이 일어나고 있는지 그리고이 상황에서 가장 좋은 방법이 무엇인지를 이해하는 것입니다. 여기 간다 :[NSThread의 수면 :] : MPMediaItem을 첨부 응용 프로그램에서</p> <pre><code>[NSThread sleepForTimeInterval:0.1]; </code></pre> <p>(음악/이미지) 속성을 그냥 교착 상태 또는 동기화 문제를 가진 것으로 보이는 "해결"

제조법을 복제하기 위해 다음과 같이 모든 시간은 다음과 같습니다

  1. 사용자가 새 프로젝트를 생성합니다.

    doc = [[UIManagedDocument alloc] initWithFileURL:docURL]; 
    
    if (![[NSFileManager defaultManager] fileExistsAtPath:[docURL path]]) { 
        [doc saveToURL:docURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { 
        if (success) { 
         completionBlock(doc); 
        } 
        else { 
         DLog(@"Failed document creation: %@", doc.localizedName); 
        } 
    }]; 
    
  2. 나중에 managedObjectContext가 CoreData 모델

    TheProject *theProject = [TheProject projectWithInfo:theProjectInfo 
               inManagedObjectContext:doc.managedObjectContext]; 
    
  3. 사용자는 나중에 "에서 CustomAction"객체를 생성을 객체 인스턴스를 연결하고 수화 사용되며, 그와 동료에게 "ChElement"을 추가 ChElement를 가진 "MusicElement". CoreData 모델 객체의 가명입니다. MusicElement는 IPOD 라이브러리를 통해 추가됩니다.

    #define PLAYER [MPMusicPlayerController iPodMusicPlayer] 
    
  4. 사용자는이 프로젝트를 저장 이미 ChElement 및 MusicElement으로 만든 하나에서 CustomAction 개체가 기존 프로젝트로 전환.

  5. 사용자가 tableView에서 해당 ChElement를 선택하고 detailView로 이동합니다. ChElementTVC (애플의 문서에서 발견되는 것과 유사한 CoreData TableViewController 클래스의 서브 클래스)에서 멀리 탐색 할 때 ,이가 필요합니다

    상세보기에서
    - (void)viewWillDisappear:(BOOL)animated 
    { 
        [super viewWillDisappear:animated]; 
        self.fetchedResultsController.delegate = nil; 
    } 
    
  6. 는, 사용자가 ChElement 객체의 속성을 변경 프로젝트를 저장합니다. detailView는 대리자 (ChElementTVC)를 호출하여 저장 작업을 수행합니다. 저장은 NSManagedObject를 보유하고있는 UIManagedDocument 인스턴스에 저장됩니다. 델리게이트 (ChElementTVC)는 탐색 스택 오프 detailView 튀어 때문에

    #define SAVEDOC(__DOC__) [ProjectDocumentHelper saveProjectDocument:__DOC__] 
    
    // Delegate 
    
    - (void)chAddElementDetailViewController:(ChDetailViewController *)sender didPressSaveButton:(NSString *)message 
    { 
        SAVEDOC(THE_CURRENT_PROJECT_DOCUMENT); 
    
        [self.navigationController popViewControllerAnimated:YES]; 
    } 
    
    
    // Helper Class 
    
    + (void)saveProjectDocument:(UIManagedDocument *)targetDocument 
    { 
        NSManagedObjectContext *moc = targetDocument.managedObjectContext; 
        [moc performBlockAndWait:^{ 
         DLog(@" Process Pending Changes before saving : %@, Context = %@", targetDocument.description, moc); 
    
         [moc processPendingChanges]; 
         [targetDocument saveToURL:targetDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL]; 
        }]; 
    } 
    
  7. 는 그 viewWillAppear가 호출되고 fetchedResultsController.delegate 복원된다. [NSThread sleepForTimeInterval:0.1]; 응용 프로그램의 중단없이

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    if (!self.fetchedResultsController.delegate) { 

     DLog(@"Sleep Now %@", self); 

     //http://mobiledevelopertips.com/core-services/sleep-pause-or-block-a-thread.html 

     [NSThread sleepForTimeInterval:0.1]; 

     DLog(@"Wake up %@", self); 

     [self fetchedResultsControllerWithPredicate:_savedPredicate]; // App Hangs Here ... This is sending messages to CoreData objects. 

     [self.tableView reloadData]; 
} 

. 이

(lldb) 프레임이 5

frame #5: 0x35860564 CoreData _perform + 160 
    CoreData _perform + 160: 
    -> 0x35860564: add sp, #12 
     0x35860566: pop {r4, r5, r7, pc} 

    CoreData -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]: 
     0x35860568: push {r4, r5, r6, r7, lr} 
     0x3586056a: add r7, sp, #12 

(lldb)를 선택 분해

* thread #1: tid = 0x1c03, 0x30e06054 libsystem_kernel.dylib semaphore_wait_trap + 8, stop reason = signal SIGINT 
    frame #0: 0x30e06054 libsystem_kernel.dylib semaphore_wait_trap + 8 
    frame #1: 0x32c614f4 libdispatch.dylib _dispatch_thread_semaphore_wait$VARIANT$mp + 12 
    frame #2: 0x32c5f6a4 libdispatch.dylib _dispatch_barrier_sync_f_slow + 92 
    frame #3: 0x32c5f61e libdispatch.dylib dispatch_barrier_sync_f$VARIANT$mp + 22 
    frame #4: 0x32c5f266 libdispatch.dylib dispatch_sync_f$VARIANT$mp + 18 
    frame #5: 0x35860564 CoreData _perform + 160 
BT는

(lldb) - : 나는 엑스 코드를 통해 SIGINT를 보낼 때, 나는 디버거를 얻을 다음과 같은 공개 f

CoreData _perform: 
     0x358604c4: push {r4, r5, r7, lr} 

    ... snipped ... 

     0x35860560: blx 0x35938bf4    ; symbol stub for: dispatch_sync_f 

    -> 0x35860564: add sp, #12 
     0x35860566: pop {r4, r5, r7, pc} 

또 다른 해결 방법이 있습니다. fetchedResultsController 코딩하기.-[ChElementTVC viewDidAppear:]의 대리자 복원도 효과적으로이 설정을 기본 대기열에서 지연시킵니다.

추가 해결 방법 프로젝트 저장이 완료된 후 완료 블록에서 탐색 팝업을 실행하는 것입니다

#define SAVEDOCWITHCOMPLETION(__DOC__,__COMPLETION_BLOCK__)[ProjectDocumentHelper saveProjectDocument:__DOC__ completionHandler:__COMPLETION_BLOCK__] 

    void (^completionBlock)(BOOL) = ^(BOOL success) { 
     [self.navigationController popViewControllerAnimated:YES]; 
    }; 

    SAVEDOCWITHCOMPLETION(THE_CURRENT_PROJECT_DOCUMENT, completionBlock); 

를 내가 작업이 주에 위임 복원과 동시에 백그라운드에서 실행 저장 생각 대기열,하지만 그 이론을 검사/증명/반증하는 방법을 모르겠습니다.

그럼, 누군가가 무슨 일이 일어나고 있는지,이 상황에서 가장 좋은 방법은 무엇인지 설명 할 수 있습니까? 또한 연구 참고 문헌을 참고할 수 있습니다.

답변

1

마지막으로 세 번째 방법 인 CoreData 저장소와 상호 작용하는 트랜잭션을 직렬화하기 위해 완료 블록으로 문서를 저장하는 방법을 구현했습니다.