UITableViewController에서 UISearchDisplayController를 사용할 때 어설 션 실패
내 앱의 TableViewController에 간단한 검색 기능을 추가하려고했습니다. Ray Wenderlich의 튜토리얼을 따랐습니다. 일부 데이터가있는 tableView가 있고 스토리 보드에 검색 막대 + 디스플레이 컨트롤러를 추가 한 다음이 코드가 있습니다.
#pragma mark - Table View
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BreedCell" forIndexPath:indexPath];
//Create PetBreed Object and return corresponding breed from corresponding array
PetBreed *petBreed = nil;
if(tableView == self.searchDisplayController.searchResultsTableView)
petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row];
else
petBreed = [_breedsArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = petBreed.name;
return cell;
}
#pragma mark - Search
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[_filteredBreedsArray removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchString];
_filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy];
return YES;
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
// Tells the table data source to reload when scope bar selection changes
[_filteredBreedsArray removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",self.searchDisplayController.searchBar.text];
_filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy];
return YES;
}
표준 항목이지만 검색 창에 텍스트를 입력하면 매번이 오류와 함께 충돌합니다.
2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Assertion failure in -[UISearchResultsTableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460
2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier BreedCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
iOS 6에서 셀 처리 및 대기열에서 빼기 시스템이 변경되었고 검색이 다른 tableView를 사용한다는 것을 알고 있으므로 필터링 된 결과가있는 검색 tableView가 셀에 대해 알지 못한다는 문제가 있다고 생각했기 때문에 이것은 내 viewDidLoad에서 :
[self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"BreedCell"];
그리고 짜잔! 효과가 ... 처음 검색했을 때만. 원래 결과로 돌아가 다시 검색하면 앱이 동일한 오류와 함께 충돌합니다. 나는 아마 모든 것을 추가하는 것에 대해 생각했다.
if(!cell){//init cell here};
물건을 cellForRow 메서드에 추가하지만 dequeueReusableCellWithIdentifier : forIndexPath : 메서드를 갖는 전체 목적에 위배되지 않습니까? 어쨌든 길을 잃었습니다. 내가 무엇을 놓치고 있습니까? 도와주세요. 시간 내 주셔서 미리 감사드립니다 (:
알렉스.
dequeueReusableCellWithIdentifier에서 tableView 대신 self.tableView를 사용해보십시오.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"BreedCell"];
//Create PetBreed Object and return corresponding breed from corresponding array
PetBreed *petBreed = nil;
if(tableView == self.searchDisplayController.searchResultsTableView)
petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row];
else
petBreed = [_breedsArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = petBreed.name;
return cell;
}
이 코드는 꽤 잘 작동합니다.
노트
사용자 지정 높이 셀이있는 경우 사용하지 마십시오.
[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
대신 사용
[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
첫 번째 실행에서는 훌륭하게 작동했지만 결과 테이블을 종료하고 다른 검색을 위해 다시 UITableView들어가면 충돌이 발생하는 이유는 검색 모드에 들어갈 때마다 검색 디스플레이 컨트롤러가 새 항목을로드하기 때문 입니다.
By search mode I mean, you've tapped the textfield and you've began to type, at which point a table view is generated to display results, exiting this mode it achieved by hitting the cancel button. When you tap the textfield the second time and begin typing again - this is entering "search mode" for the second time.
So in order to avoid the crash you should register the cell class for the table view to use in the searchDisplayController:didLoadSearchResultsTableView: delegate method (from UISearchDisplayDelegate) of instead of in your controllers viewDidLoad method.
As follows:
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
[tableView registerClass:[DPContentTableCell class] forCellReuseIdentifier:cellIdentifier];
[tableView registerClass:[DPEmptyContentTableCell class] forCellReuseIdentifier:emptyCellIdentifier];
}
This caught me by surprise because on iOS 7... the table view is being reused. So you can register the class in viewDidLoad if you prefer. For legacy sakes, I'll keep my registration in the delegate method I mentioned.
After searching, 'tableView' of cellForRowAtIndexPath method seems not an instance of the Table that you define. So, you can use an instance of a table that defines the cell. Instead of:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
Use:
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
(Do not use the tableView of cellForRowAtIndexPath method, use self.tableView.)
Dequeue the cell without using the 'indexPath' and in case of you obtain a nil element, you have to allocate it manually.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YourCellId"];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"YourCellId"];
// fill your cell object with useful stuff :)
return cell;
}
Trying to use self.tableView for dequeue the cell may cause crashes when you have a sectioned main list and a plain search list. This code instead work in any situation.
When I had this problem, the solution was replacing tableView dequeueReusableCellWithIdentifier:@yourcell with self.tableView
I am working on that tutorial also. The default TableViewController has "forIndexPath" and in his example it doesn't exist. Once I removed it the search works.
//Default code
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Replace with
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
for swift 3 you just need to add self:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! YourCell
...
}
'Program Club' 카테고리의 다른 글
| Dalvik 형식으로 변환 실패 : dex를 실행할 수 없음 : Java 힙 공간 (0) | 2020.10.08 |
|---|---|
| JavaScript를 통해 쿼리 문자열 값이 있는지 확인하는 방법은 무엇입니까? (0) | 2020.10.08 |
| .NET에서 생성 날짜별로 파일 가져 오기 (0) | 2020.10.08 |
| java.lang.ClassNotFoundException : Eclipse의 com.mysql.jdbc.Driver (0) | 2020.10.08 |
| NPM이 멈춰서 동일한 오류가 발생합니다. EISDIR : 디렉터리에 대한 잘못된 작업, 오류시 읽기 (기본) (0) | 2020.10.08 |