2011-06-11 3 views
1

나는 비동기 적으로 데이터를 가져 오는거야, 나는 가이드로 이것을 사용했습니다 : http://deeperdesign.wordpress.com/2011/05/30/cancellable-asynchronous-searching-with-uisearchdisplaycontroller/NSRangeException

모든 지금

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{  
//setup request/predicate etc...    
[self.searchQueue addOperationWithBlock:^{ 
      NSError *error;    
      self.matchingObjects = [self.managedObjectContext executeFetchRequest:request error:&error]; 
      [request release]; 

      [[NSOperationQueue mainQueue] addOperationWithBlock:^ 
       { 
        [self.searchDisplayController.searchResultsTableView reloadData]; 
       }]; 

    }];    
    // Return YES to cause the search result table view to be reloaded. 
    return NO; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{  
     // Return the number of rows in the section. 
     return [self.matchingObjects count]; 
} 

에서 다음 내가 뭔가를 얻을 수 있습니다 테이블 셀을 구성 할 때이 액세스가 matchingObjects 아이바 던져

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 0 beyond bounds for empty array' 

: 효과

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

항상 충돌이 발생하지 않고 임의의 경우에 발생하는 것 같습니다. 나는 어딘가에 matchingObjects 배열의 개수가 변경되고 업데이트되지 않는 특정 값을 반환하고 있다고 생각합니다.

나는 이것을 어떻게 다루어야하는지 완전히 확신하지 못합니다. 몇 시간 동안 이것을보고 있었는데, 제가 빠진 것이 있습니까?

답변

1

나는 그것이 무엇인지 알아 냈습니다. 잠시 시간이 걸렸지 만, 방금 연결 한 예제를 다시 보았습니다. 백그라운드 스레드에서 self.matchingObjects iVar를 업데이트 할 때 어떤 경우에는 주 스레드에서 사용할 수있는 배열 범위와 백그라운드 스레드 사이의 불일치가 발생했습니다. 예를 들어 변수가 백그라운드 스레드에서 업데이트되었을 수 있고 변수가 업데이트 된 이후 더 이상 존재하지 않는 범위의 일부에 주 스레드가 여전히 액세스하고있을 수 있습니다.

다음과 같이 내 코드를 개정하여 고정 :

[self.searchQueue addOperationWithBlock:^ 
{ 
    NSError *error; 

    NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error]; 
    [request release]; 

    [[NSOperationQueue mainQueue] addOperationWithBlock:^ 
    { 
     self.matchingObjects = results; 
     [self.searchDisplayController.searchResultsTableView reloadData]; 
    }]; 

}]; 

이제 검색 결과가 "결과"라는 임시로 보관 배열로로드하고, matchingObjects 바르가 처음으로 메인 스레드에 업데이트되며, 그러면 tableView가 다시로드됩니다. 이렇게하면 tableView는 항상 액세스되는 동안 변경되지 않는 배열을 참조합니다. tableView는 matchingObjects를 사용하여 행 및 데이터의 수를 얻으므로 해당 배열에 액세스하는 동안 항상 변경되지 않습니다.

관련 문제