2016-10-04 10 views
0

私はUITableViewController内にUISearchControllerを持っています。私は、テーブルビューが表示されるたびに、最後に検索されたテキストを検索バーに挿入します。このため、最後の検索文字列を取得してUISearchControllerをアクティブにするために、viewDidAppearにコードを追加しました。検索結果が空の場合、UITableViewのUISearchControllerがクラッシュします。

検索テキストを入力しなくても、すべて正常に機能します。

検索テキストを入力すると、初めて検索が正常に動作します。しかし、このビューを再度開いてUISearchControllerに最後の検索語を入力すると、新しいリストが空の結果を返す場合(tableview内のリストが動的なために可能です)、cellForRowAtIndexPathでアプリがクラッシュして行を空の検索結果配列にアクセスします。

私は多くの場所にNSLogsを置き、奇妙なことを発見しました。 UISearchControllerがアクティブであっても、numberOfRowsInSectionの対応する条件はFALSEを返し、検索された項目リスト(現在は0)ではなく元の項目リストの項目数を返します。検索コントローラが代わりに行こうと、アクティブなとき

それは、その機能の句「([_searchControllerのisActive])であれば」、numOfRowsInSectionを呼び出し、それが誤っは、(元のリストのカウントを取得し、「他の」句で行きます不思議なことに、cellForRowAtIndexPathでは、実際にが正しく "if(_searchController.active)"句の中に入ります。明らかに競合状態があるか、何か不足しています。

なぜこれが起こっているのか非常に混乱しています。助けていただければ幸いです。

@interface TaalListViewController() 

@property (strong, nonatomic) NSArray *m_searchedItemList; 
@property NSArray *m_itemList; 
@property (retain, nonatomic) UISearchController *searchController; 

@end 

@implementation TaalListViewController 

- (id)initWithStyle:(UITableViewStyle)style 
{ 
    self = [super initWithStyle:style]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

- (void)viewDidLoad 
{ 
    @try { 
     [super viewDidLoad]; 

     // Uncomment the following line to preserve selection between presentations. 
     // self.clearsSelectionOnViewWillAppear = NO; 

     // This is a global function declared and returns the items list. This works fine. 
     _m_itemList = [Globals getItemsList]; 

     // Search controller 
     _m_searchedItemList = [_m_itemList mutableCopy]; 

     self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; 
     self.searchController.searchBar.delegate = self; 
     self.searchController.searchResultsUpdater = self; 
     [self.searchController.searchBar sizeToFit]; 
     self.searchController.dimsBackgroundDuringPresentation = NO; 
     self.definesPresentationContext = YES; 
     self.tableView.tableHeaderView = self.searchController.searchBar; 
    } 
    @catch (NSException *exception) { 
     NSLog(@"Caught exception in viewDidLoad"); 
     NSLog(@"CRASH: %@", exception); 
     NSLog(@"Stack Trace: %@", [exception callStackSymbols]); 
    } 
} 


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

    // Get the last searched text and automatically set it in the search bar 
    NSString *str = [Globals getLastSearchedText]; 
    if ((str != nil) && (!(str.length == 0))) 
    { 
     NSLog(@"Setting seach bar active automatically"); 
     self.searchController.searchBar.text = str; 
     self.searchController.active = YES; 
     // [self.searchController.searchBar becomeFirstResponder]; 
    } 
} 

#pragma mark - Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    // Return the number of sections. 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    @try { 
     // Return the number of rows in the section. 
     if ([self.searchController isActive]) 
     { 
      NSLog(@"Number of searched item rows = %lu", (unsigned long)_m_searchedItemList.count); 
      return _m_searchedItemList.count; 
     } 
     else 
     { 
      NSLog(@"Number of regular rows = %lu", (unsigned long)_m_itemList.count); 
      return _m_itemList.count; 
     } 
    } 
    @catch (NSException *exception) { 
     NSLog(@"Caught exception in numberOfRowsInSection"); 
     NSLog(@"CRASH: %@", exception); 
     NSLog(@"Stack Trace: %@", [exception callStackSymbols]); 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    @try { 
     static NSString *CellIdentifier = @"ListTableCell"; 

     ListTableViewCell *cell = (ListTableViewCell *) [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

     // Configure the cell... 
     if (cell == nil) 
     { 
      cell = [[ListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
     } 

     DisplayListItem *item = nil; 

     if (self.searchController.active) 
     { 
      NSLog(@"Row %ld of search list", (long)indexPath.row); 
      item = (DisplayListItem *) [_m_searchedItemList objectAtIndex:indexPath.row]; 
     } 
     else 
     { 
      NSLog(@"Row %ld of regular list", (long)indexPath.row); 
      item = (DisplayListItem *) [_m_itemList objectAtIndex:indexPath.row]; 
     } 

     // Set the cell here and return 
     // ... 
     // Omitted code 
     // ... 

     return cell; 
    } 
    @catch (NSException *exception) { 
     NSLog(@"Caught exception in cellForRowAtIndexPath"); 
     NSLog(@"CRASH: %@", exception); 
     NSLog(@"Stack Trace: %@", [exception callStackSymbols]); 
    } 
} 

#pragma mark - UISearchResultsUpdating 

-(void)updateSearchResultsForSearchController:(UISearchController *)searchController { 

    NSString *searchString = [self.searchController.searchBar text]; 

    NSLog(@"updateSearchResultsForSearchController called, searchString = %@", searchString); 

    _m_searchedItemList = [_m_itemList mutableCopy]; 

    if (searchString.length != 0) 
    { 
     [self filterContentForSearchText:searchString]; 
    } 

    [self.tableView reloadData]; 
} 

#pragma mark - UISearchBarDelegate 

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { 
    NSLog(@"searchBarSearchButtonClicked called"); 
    [searchBar resignFirstResponder]; 
} 

- (void)filterContentForSearchText:(NSString*)searchText 
{ 
    NSLog(@"filterContentForSearchText called"); 
    @try { 

     NSMutableArray *subPredicates = [NSMutableArray arrayWithCapacity:searchText.count]; 
     for (NSString *searchStr in searchText) 
     { 
      [subPredicates addObject:[NSPredicate predicateWithFormat:@"m_name contains[c] %@", searchStr]]; 
     } 
     NSPredicate *resultPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates]; 
     _m_searchedItemList = [_m_itemList filteredArrayUsingPredicate:resultPredicate]; 

     [Globals setLastSearchedText:searchText]; 

     NSLog(@"filterContentForSearchText finished, searched count = %lu", _m_searchedItemList.count); 
    } 
    @catch (NSException *exception) { 
     NSLog(@"Caught exception in filterContentForSearchText"); 
     NSLog(@"CRASH: %@", exception); 
     NSLog(@"Stack Trace: %@", [exception callStackSymbols]); 
    } 
} 

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText 
{ 
    [Globals setLastSearchedText:searchText]; 
} 
@end 

ここに、デバッガでのNSLogsの出力があります。

2016-10-04 22:45:46.364927 AppName[1387:639346] Setting seach bar active automatically 
2016-10-04 22:45:46.365378 AppName[1387:639346] updateSearchResultsForSearchController called, searchString = Kay 
2016-10-04 22:45:46.365470 AppName[1387:639346] filterContentForSearchText called 
2016-10-04 22:45:46.366522 AppName[1387:639346] filterContentForSearchText finished, searched count = 0 
2016-10-04 22:45:46.366825 AppName[1387:639346] Number of regular rows = 215 
2016-10-04 22:45:46.367319 AppName[1387:639346] updateSearchResultsForSearchController called, searchString = Kay 
2016-10-04 22:45:46.367407 AppName[1387:639346] filterContentForSearchText called 
2016-10-04 22:45:46.368190 AppName[1387:639346] filterContentForSearchText finished, searched count = 0 
2016-10-04 22:45:46.368264 AppName[1387:639346] Number of regular rows = 215 
2016-10-04 22:45:46.371081 AppName[1387:639346] Row 0 of search list 
2016-10-04 22:45:46.373274 AppName[1387:639346] Caught exception in cellForRowAtIndexPath 
2016-10-04 22:45:46.373383 AppName[1387:639346] CRASH: *** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray 
2016-10-04 22:45:46.382029 AppName[1387:639346] Stack Trace: (
    0 CoreFoundation      0x0000000192d981d8 <redacted> + 148 
    1 libobjc.A.dylib      0x00000001917d055c objc_exception_throw + 56 
    2 CoreFoundation      0x0000000192d033dc <redacted> + 0 
    3 AppName        0x00000001001269bc -[ListViewController tableView:cellForRowAtIndexPath:] + 512 
    4 UIKit        0x0000000198f243d4 <redacted> + 716 
    5 UIKit        0x0000000198f24604 <redacted> + 80 
    6 UIKit        0x0000000198f11bac <redacted> + 2304 
    7 UIKit        0x0000000198f29668 <redacted> + 116 
    8 UIKit        0x0000000198cc5b14 <redacted> + 176 
    9 UIKit        0x0000000198bde54c <redacted> + 1196 
    10 QuartzCore       0x00000001960a640c <redacted> + 148 
    11 QuartzCore       0x000000019609b0e8 <redacted> + 292 
    12 QuartzCore 
2016-10-04 22:45:46.382306 AppName[1387:639346] -[_UITableViewReorderingSupport _needsSetup]: unrecognized selector sent to instance 0x170290e00 
2016-10-04 22:45:46.382714 AppName[1387:639346] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_UITableViewReorderingSupport _needsSetup]: unrecognized selector sent to instance 0x170290e00' 
*** First throw call stack: 
(0x192d981c0 0x1917d055c 0x192d9f278 0x192d9c278 0x192c9659c 0x198d22c6c 0x198f24440 0x198f24604 0x198f11bac 0x198f29668 0x198cc5b14 0x198bde54c 0x1960a640c 0x19609b0e8 0x19609afa8 0x196017c64 0x19603f0d0 0x19603faf0 0x192d457dc 0x192d4340c 0x192d4389c 0x192c72048 0x1946f5198 0x198c4c628 0x198c47360 0x10015aaa8 0x191c545b8) 
libc++abi.dylib: terminating with uncaught exception of type NSException 
+1

使用する前に配列を初期化します。 –

+0

私は既に配列を初期化しています://これは宣言されたグローバル関数であり、項目リストを返します。これは正常に動作します。 _m_itemList = [グローバルなgetItemsList]; //検索コントローラ _m_searchedItemList = [_m_itemList mutableCopy];このコードは既にviewDidLoadで初期化されています。 – Abhijit

+0

スクロール中にsearchmodeを離れるとき、この動作を見た... numberOfRowsでは、cellContRowAtIndexPathを実行しているときにsearchController isActiveがYESだった(スクロールのため)... – Tobias

答えて

0
2016-10-04 22:45:46.373274 AppName[1387:639346] Caught exception in cellForRowAtIndexPath 
2016-10-04 22:45:46.373383 AppName[1387:639346] CRASH: *** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray 

右がそれを言います! cellForRowAtIndexPathで空の要素0にアクセスしようとしていますNSArray

これを行わないとクラッシュしません!

+0

これを理解している。問題は - numOfRowsInSectionを呼び出し、その関数のif([_searchController isActive])節に入るのではなく、 "else"節に入り、元のリストの数(検索されていない)を取得してから呼び出します間違ったindexPathを持つcellForRowAtIndexPath。さらに奇妙なことに、cellForRowAtIndexPathでは、実際には "if(_searchController.active)"節の中に正しく入ります。明らかに競合状態があるか、何か不足しています。 – Abhijit

+0

質問を上記のコメントで更新しました。 – Abhijit

関連する問題