如何使用UISearchDisplayController / UISearchBar过滤

如何使用UISearchDisplayController / UISearchBar过滤NSFetchedResultsController(CoreData)

我正在尝试在基于CoreData的iPhone应用程序中实现搜索代码。我不知道该怎么办。该应用程序已经有一个带有谓词的NSFetchedResultsController,用于检索主TableView的数据。在改变太多代码之前,我想确保自己走在正确的道路上。我很困惑,因为很多例子都是基于数组而不是CoreData。

以下是一些问题:

  1. 我是否需要第二个NSFetchedResultsController只检索匹配的项目,或者我可以使用与主TableView相同的项目吗?

  2. 如果我使用相同的,它是否像清除FRC缓存然后更改handleSearchForTerm:searchString方法中的谓词一样简单?谓词是否必须包含初始谓词以及搜索词,还是记得它首先使用谓词来检索数据?

  3. 我如何回到原始结果?我只是将搜索谓词设置为nil吗?难道不会杀掉用于首先检索FRC结果的原始谓词吗?

如果有人使用FRC搜索任何代码示例,我将不胜感激!


一只甜甜圈
浏览 574回答 3
3回答

慕容708150

我实际上只是在我的一个项目上实现了这个(你的问题和另一个错误的答案暗示了该做什么)。我尝试了Sergio的回答但在实际运行在设备上时遇到异常问题。是的,您创建了两个获取结果控制器:一个用于正常显示,另一个用于UISearchBar的表视图。如果您只使用一个FRC(NSFetchedResultsController),则原始UITableView(不是搜索时处于活动状态的搜索表视图)可能会在您搜索时调用回调并尝试错误地使用FRC的过滤版本,您将看到异常抛出部分中不正确数量的部分或行。这是我做的:我有两个FRC可用作属性fetchedResultsController和searchFetchedResultsController。除非有搜索,否则不应使用searchFetchedResultsController(当取消搜索时,您可以在下面看到该对象已被释放)。所有UITableView方法都必须弄清楚它将查询哪个表视图以及从中提取信息的适用FRC。FRC委托方法还必须确定要更新的tableView。令人惊讶的是,这有多少是样板代码。头文件的相关位:@interface&nbsp;BlahViewController&nbsp;:&nbsp;UITableViewController&nbsp;<UISearchBarDelegate,&nbsp;NSFetchedResultsControllerDelegate,&nbsp;UISearchDisplayDelegate>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;other&nbsp;class&nbsp;ivars &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;required&nbsp;ivars&nbsp;for&nbsp;this&nbsp;example &nbsp;&nbsp;&nbsp;&nbsp;NSFetchedResultsController&nbsp;*fetchedResultsController_; &nbsp;&nbsp;&nbsp;&nbsp;NSFetchedResultsController&nbsp;*searchFetchedResultsController_; &nbsp;&nbsp;&nbsp;&nbsp;NSManagedObjectContext&nbsp;*managedObjectContext_; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;The&nbsp;saved&nbsp;state&nbsp;of&nbsp;the&nbsp;search&nbsp;UI&nbsp;if&nbsp;a&nbsp;memory&nbsp;warning&nbsp;removed&nbsp;the&nbsp;view. &nbsp;&nbsp;&nbsp;&nbsp;NSString&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*savedSearchTerm_; &nbsp;&nbsp;&nbsp;&nbsp;NSInteger&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;savedScopeButtonIndex_; &nbsp;&nbsp;&nbsp;&nbsp;BOOL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;searchWasActive_;}@property&nbsp;(nonatomic,&nbsp;retain)&nbsp;NSManagedObjectContext&nbsp;*managedObjectContext;@property&nbsp;(nonatomic,&nbsp;retain,&nbsp;readonly)&nbsp;NSFetchedResultsController&nbsp;*fetchedResultsController;@property&nbsp;(nonatomic,&nbsp;copy)&nbsp;NSString&nbsp;*savedSearchTerm;@property&nbsp;(nonatomic)&nbsp;NSInteger&nbsp;savedScopeButtonIndex;@property&nbsp;(nonatomic)&nbsp;BOOL&nbsp;searchWasActive;相关位的实现文件:@interface&nbsp;BlahViewController&nbsp;()@property&nbsp;(nonatomic,&nbsp;retain)&nbsp;NSFetchedResultsController&nbsp;*fetchedResultsController;@property&nbsp;(nonatomic,&nbsp;retain)&nbsp;NSFetchedResultsController&nbsp;*searchFetchedResultsController;@property&nbsp;(nonatomic,&nbsp;retain)&nbsp;UISearchDisplayController&nbsp;*mySearchDisplayController;@end在使用所有UITableViewDelegate / DataSource方法时,我创建了一个有用的方法来检索正确的FRC:-&nbsp;(NSFetchedResultsController&nbsp;*)fetchedResultsControllerForTableView:(UITableView&nbsp;*)tableView{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;tableView&nbsp;==&nbsp;self.tableView&nbsp;?&nbsp;self.fetchedResultsController&nbsp;:&nbsp;self.searchFetchedResultsController;}-&nbsp;(void)fetchedResultsController:(NSFetchedResultsController&nbsp;*)fetchedResultsController&nbsp;configureCell:(UITableViewCell&nbsp;*)theCell&nbsp;atIndexPath:(NSIndexPath&nbsp;*)theIndexPath{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;your&nbsp;cell&nbsp;guts&nbsp;here}-&nbsp;(UITableViewCell&nbsp;*)tableView:(UITableView&nbsp;*)theTableView&nbsp;cellForRowAtIndexPath:(NSIndexPath&nbsp;*)theIndexPath{ &nbsp;&nbsp;&nbsp;&nbsp;CallTableCell&nbsp;*cell&nbsp;=&nbsp;(CallTableCell&nbsp;*)[theTableView&nbsp;dequeueReusableCellWithIdentifier:@"CallTableCell"]; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(cell&nbsp;==&nbsp;nil)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell&nbsp;=&nbsp;[[[CallTableCell&nbsp;alloc]&nbsp;initWithStyle:UITableViewCellStyleDefault&nbsp;reuseIdentifier:@"CallTableCell"]&nbsp;autorelease]; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[self&nbsp;fetchedResultsController:[self&nbsp;fetchedResultsControllerForTableView:theTableView]&nbsp;configureCell:cell&nbsp;atIndexPath:theIndexPath]; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;cell;}-&nbsp;(NSInteger)numberOfSectionsInTableView:(UITableView&nbsp;*)tableView&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;NSInteger&nbsp;count&nbsp;=&nbsp;[[[self&nbsp;fetchedResultsControllerForTableView:tableView]&nbsp;sections]&nbsp;count]; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;count;}-&nbsp;(NSInteger)tableView:(UITableView&nbsp;*)tableView&nbsp;numberOfRowsInSection:(NSInteger)section&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;NSInteger&nbsp;numberOfRows&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;NSFetchedResultsController&nbsp;*fetchController&nbsp;=&nbsp;[self&nbsp;fetchedResultsControllerForTableView:tableView]; &nbsp;&nbsp;&nbsp;&nbsp;NSArray&nbsp;*sections&nbsp;=&nbsp;fetchController.sections; &nbsp;&nbsp;&nbsp;&nbsp;if(sections.count&nbsp;>&nbsp;0)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;<NSFetchedResultsSectionInfo>&nbsp;sectionInfo&nbsp;=&nbsp;[sections&nbsp;objectAtIndex:section]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numberOfRows&nbsp;=&nbsp;[sectionInfo&nbsp;numberOfObjects]; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;numberOfRows;}委托搜索栏的方法:#pragma&nbsp;mark&nbsp;-#pragma&nbsp;mark&nbsp;Content&nbsp;Filtering-&nbsp;(void)filterContentForSearchText:(NSString*)searchText&nbsp;scope:(NSInteger)scope{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;update&nbsp;the&nbsp;filter,&nbsp;in&nbsp;this&nbsp;case&nbsp;just&nbsp;blow&nbsp;away&nbsp;the&nbsp;FRC&nbsp;and&nbsp;let&nbsp;lazy&nbsp;evaluation&nbsp;create&nbsp;another&nbsp;with&nbsp;the&nbsp;relevant&nbsp;search&nbsp;info &nbsp;&nbsp;&nbsp;&nbsp;self.searchFetchedResultsController.delegate&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;self.searchFetchedResultsController&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;if&nbsp;you&nbsp;care&nbsp;about&nbsp;the&nbsp;scope&nbsp;save&nbsp;off&nbsp;the&nbsp;index&nbsp;to&nbsp;be&nbsp;used&nbsp;by&nbsp;the&nbsp;serchFetchedResultsController &nbsp;&nbsp;&nbsp;&nbsp;//self.savedScopeButtonIndex&nbsp;=&nbsp;scope;}#pragma&nbsp;mark&nbsp;-#pragma&nbsp;mark&nbsp;Search&nbsp;Bar&nbsp;-&nbsp;(void)searchDisplayController:(UISearchDisplayController&nbsp;*)controller&nbsp;willUnloadSearchResultsTableView:(UITableView&nbsp;*)tableView;{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;search&nbsp;is&nbsp;done&nbsp;so&nbsp;get&nbsp;rid&nbsp;of&nbsp;the&nbsp;search&nbsp;FRC&nbsp;and&nbsp;reclaim&nbsp;memory &nbsp;&nbsp;&nbsp;&nbsp;self.searchFetchedResultsController.delegate&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;self.searchFetchedResultsController&nbsp;=&nbsp;nil;}-&nbsp;(BOOL)searchDisplayController:(UISearchDisplayController&nbsp;*)controller&nbsp;shouldReloadTableForSearchString:(NSString&nbsp;*)searchString{ &nbsp;&nbsp;&nbsp;&nbsp;[self&nbsp;filterContentForSearchText:searchString&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scope:[self.searchDisplayController.searchBar&nbsp;selectedScopeButtonIndex]]; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Return&nbsp;YES&nbsp;to&nbsp;cause&nbsp;the&nbsp;search&nbsp;result&nbsp;table&nbsp;view&nbsp;to&nbsp;be&nbsp;reloaded. &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;YES;}-&nbsp;(BOOL)searchDisplayController:(UISearchDisplayController&nbsp;*)controller&nbsp;shouldReloadTableForSearchScope:(NSInteger)searchOption{ &nbsp;&nbsp;&nbsp;&nbsp;[self&nbsp;filterContentForSearchText:[self.searchDisplayController.searchBar&nbsp;text]&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scope:[self.searchDisplayController.searchBar&nbsp;selectedScopeButtonIndex]]; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Return&nbsp;YES&nbsp;to&nbsp;cause&nbsp;the&nbsp;search&nbsp;result&nbsp;table&nbsp;view&nbsp;to&nbsp;be&nbsp;reloaded. &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;YES;}从FRC委托方法获取更新时,请确保使用正确的表视图:-&nbsp;(void)controllerWillChangeContent:(NSFetchedResultsController&nbsp;*)controller&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;UITableView&nbsp;*tableView&nbsp;=&nbsp;controller&nbsp;==&nbsp;self.fetchedResultsController&nbsp;?&nbsp;self.tableView&nbsp;:&nbsp;self.searchDisplayController.searchResultsTableView; &nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;beginUpdates];}-&nbsp;(void)controller:(NSFetchedResultsController&nbsp;*)controller&nbsp; &nbsp;&nbsp;didChangeSection:(id&nbsp;<NSFetchedResultsSectionInfo>)sectionInfo &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atIndex:(NSUInteger)sectionIndex&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;forChangeType:(NSFetchedResultsChangeType)type&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;UITableView&nbsp;*tableView&nbsp;=&nbsp;controller&nbsp;==&nbsp;self.fetchedResultsController&nbsp;?&nbsp;self.tableView&nbsp;:&nbsp;self.searchDisplayController.searchResultsTableView; &nbsp;&nbsp;&nbsp;&nbsp;switch(type)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;NSFetchedResultsChangeInsert: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;insertSections:[NSIndexSet&nbsp;indexSetWithIndex:sectionIndex]&nbsp;withRowAnimation:UITableViewRowAnimationFade]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;NSFetchedResultsChangeDelete: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;deleteSections:[NSIndexSet&nbsp;indexSetWithIndex:sectionIndex]&nbsp;withRowAnimation:UITableViewRowAnimationFade]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;}}-&nbsp;(void)controller:(NSFetchedResultsController&nbsp;*)controller&nbsp; &nbsp;&nbsp;&nbsp;didChangeObject:(id)anObject &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atIndexPath:(NSIndexPath&nbsp;*)theIndexPath&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;forChangeType:(NSFetchedResultsChangeType)type &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newIndexPath:(NSIndexPath&nbsp;*)newIndexPath&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;UITableView&nbsp;*tableView&nbsp;=&nbsp;controller&nbsp;==&nbsp;self.fetchedResultsController&nbsp;?&nbsp;self.tableView&nbsp;:&nbsp;self.searchDisplayController.searchResultsTableView; &nbsp;&nbsp;&nbsp;&nbsp;switch(type)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;NSFetchedResultsChangeInsert: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;insertRowsAtIndexPaths:[NSArray&nbsp;arrayWithObject:newIndexPath]&nbsp;withRowAnimation:UITableViewRowAnimationFade]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;NSFetchedResultsChangeDelete: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;deleteRowsAtIndexPaths:[NSArray&nbsp;arrayWithObject:theIndexPath]&nbsp;withRowAnimation:UITableViewRowAnimationFade]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;NSFetchedResultsChangeUpdate: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self&nbsp;fetchedResultsController:controller&nbsp;configureCell:[tableView&nbsp;cellForRowAtIndexPath:theIndexPath]&nbsp;atIndexPath:theIndexPath]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;NSFetchedResultsChangeMove: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;deleteRowsAtIndexPaths:[NSArray&nbsp;arrayWithObject:theIndexPath]&nbsp;withRowAnimation:UITableViewRowAnimationFade]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;insertRowsAtIndexPaths:[NSArray&nbsp;arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;}}-&nbsp;(void)controllerDidChangeContent:(NSFetchedResultsController&nbsp;*)controller&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;UITableView&nbsp;*tableView&nbsp;=&nbsp;controller&nbsp;==&nbsp;self.fetchedResultsController&nbsp;?&nbsp;self.tableView&nbsp;:&nbsp;self.searchDisplayController.searchResultsTableView; &nbsp;&nbsp;&nbsp;&nbsp;[tableView&nbsp;endUpdates];}其他查看信息:-&nbsp;(void)loadView&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;[super&nbsp;loadView]; &nbsp;&nbsp;&nbsp;&nbsp;UISearchBar&nbsp;*searchBar&nbsp;=&nbsp;[[[UISearchBar&nbsp;alloc]&nbsp;initWithFrame:CGRectMake(0,&nbsp;0,&nbsp;self.tableView.frame.size.width,&nbsp;44.0)]&nbsp;autorelease]; &nbsp;&nbsp;&nbsp;&nbsp;searchBar.autoresizingMask&nbsp;=&nbsp;(UIViewAutoresizingFlexibleWidth); &nbsp;&nbsp;&nbsp;&nbsp;searchBar.autocorrectionType&nbsp;=&nbsp;UITextAutocorrectionTypeNo; &nbsp;&nbsp;&nbsp;&nbsp;self.tableView.tableHeaderView&nbsp;=&nbsp;searchBar; &nbsp;&nbsp;&nbsp;&nbsp;self.mySearchDisplayController&nbsp;=&nbsp;[[[UISearchDisplayController&nbsp;alloc]&nbsp;initWithSearchBar:searchBar&nbsp;contentsController:self]&nbsp;autorelease]; &nbsp;&nbsp;&nbsp;&nbsp;self.mySearchDisplayController.delegate&nbsp;=&nbsp;self; &nbsp;&nbsp;&nbsp;&nbsp;self.mySearchDisplayController.searchResultsDataSource&nbsp;=&nbsp;self; &nbsp;&nbsp;&nbsp;&nbsp;self.mySearchDisplayController.searchResultsDelegate&nbsp;=&nbsp;self;}-&nbsp;(void)didReceiveMemoryWarning{ &nbsp;&nbsp;&nbsp;&nbsp;self.searchWasActive&nbsp;=&nbsp;[self.searchDisplayController&nbsp;isActive]; &nbsp;&nbsp;&nbsp;&nbsp;self.savedSearchTerm&nbsp;=&nbsp;[self.searchDisplayController.searchBar&nbsp;text]; &nbsp;&nbsp;&nbsp;&nbsp;self.savedScopeButtonIndex&nbsp;=&nbsp;[self.searchDisplayController.searchBar&nbsp;selectedScopeButtonIndex]; &nbsp;&nbsp;&nbsp;&nbsp;fetchedResultsController_.delegate&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;[fetchedResultsController_&nbsp;release]; &nbsp;&nbsp;&nbsp;&nbsp;fetchedResultsController_&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;searchFetchedResultsController_.delegate&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;[searchFetchedResultsController_&nbsp;release]; &nbsp;&nbsp;&nbsp;&nbsp;searchFetchedResultsController_&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;[super&nbsp;didReceiveMemoryWarning];}-&nbsp;(void)viewDidDisappear:(BOOL)animated{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;save&nbsp;the&nbsp;state&nbsp;of&nbsp;the&nbsp;search&nbsp;UI&nbsp;so&nbsp;that&nbsp;it&nbsp;can&nbsp;be&nbsp;restored&nbsp;if&nbsp;the&nbsp;view&nbsp;is&nbsp;re-created &nbsp;&nbsp;&nbsp;&nbsp;self.searchWasActive&nbsp;=&nbsp;[self.searchDisplayController&nbsp;isActive]; &nbsp;&nbsp;&nbsp;&nbsp;self.savedSearchTerm&nbsp;=&nbsp;[self.searchDisplayController.searchBar&nbsp;text]; &nbsp;&nbsp;&nbsp;&nbsp;self.savedScopeButtonIndex&nbsp;=&nbsp;[self.searchDisplayController.searchBar&nbsp;selectedScopeButtonIndex];}-&nbsp;(void)viewDidLoad{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;restore&nbsp;search&nbsp;settings&nbsp;if&nbsp;they&nbsp;were&nbsp;saved&nbsp;in&nbsp;didReceiveMemoryWarning. &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(self.savedSearchTerm) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self.searchDisplayController&nbsp;setActive:self.searchWasActive]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self.searchDisplayController.searchBar&nbsp;setSelectedScopeButtonIndex:self.savedScopeButtonIndex]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self.searchDisplayController.searchBar&nbsp;setText:savedSearchTerm]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.savedSearchTerm&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;}}FRC创建代码:-&nbsp;(NSFetchedResultsController&nbsp;*)newFetchedResultsControllerWithSearch:(NSString&nbsp;*)searchString{ &nbsp;&nbsp;&nbsp;&nbsp;NSArray&nbsp;*sortDescriptors&nbsp;=&nbsp;//&nbsp;your&nbsp;sort&nbsp;descriptors&nbsp;here &nbsp;&nbsp;&nbsp;&nbsp;NSPredicate&nbsp;*filterPredicate&nbsp;=&nbsp;//&nbsp;your&nbsp;predicate&nbsp;here &nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set&nbsp;up&nbsp;the&nbsp;fetched&nbsp;results&nbsp;controller. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Create&nbsp;the&nbsp;fetch&nbsp;request&nbsp;for&nbsp;the&nbsp;entity. &nbsp;&nbsp;&nbsp;&nbsp;NSFetchRequest&nbsp;*fetchRequest&nbsp;=&nbsp;[[NSFetchRequest&nbsp;alloc]&nbsp;init]; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Edit&nbsp;the&nbsp;entity&nbsp;name&nbsp;as&nbsp;appropriate. &nbsp;&nbsp;&nbsp;&nbsp;NSEntityDescription&nbsp;*callEntity&nbsp;=&nbsp;[MTCall&nbsp;entityInManagedObjectContext:self.managedObjectContext]; &nbsp;&nbsp;&nbsp;&nbsp;[fetchRequest&nbsp;setEntity:callEntity]; &nbsp;&nbsp;&nbsp;&nbsp;NSMutableArray&nbsp;*predicateArray&nbsp;=&nbsp;[NSMutableArray&nbsp;array]; &nbsp;&nbsp;&nbsp;&nbsp;if(searchString.length) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;your&nbsp;search&nbsp;predicate(s)&nbsp;are&nbsp;added&nbsp;to&nbsp;this&nbsp;array &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[predicateArray&nbsp;addObject:[NSPredicate&nbsp;predicateWithFormat:@"name&nbsp;CONTAINS[cd]&nbsp;%@",&nbsp;searchString]]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;finally&nbsp;add&nbsp;the&nbsp;filter&nbsp;predicate&nbsp;for&nbsp;this&nbsp;view &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(filterPredicate) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filterPredicate&nbsp;=&nbsp;[NSCompoundPredicate&nbsp;andPredicateWithSubpredicates:[NSArray&nbsp;arrayWithObjects:filterPredicate,&nbsp;[NSCompoundPredicate&nbsp;orPredicateWithSubpredicates:predicateArray],&nbsp;nil]]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filterPredicate&nbsp;=&nbsp;[NSCompoundPredicate&nbsp;orPredicateWithSubpredicates:predicateArray]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[fetchRequest&nbsp;setPredicate:filterPredicate]; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Set&nbsp;the&nbsp;batch&nbsp;size&nbsp;to&nbsp;a&nbsp;suitable&nbsp;number. &nbsp;&nbsp;&nbsp;&nbsp;[fetchRequest&nbsp;setFetchBatchSize:20]; &nbsp;&nbsp;&nbsp;&nbsp;[fetchRequest&nbsp;setSortDescriptors:sortDescriptors]; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Edit&nbsp;the&nbsp;section&nbsp;name&nbsp;key&nbsp;path&nbsp;and&nbsp;cache&nbsp;name&nbsp;if&nbsp;appropriate. &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;nil&nbsp;for&nbsp;section&nbsp;name&nbsp;key&nbsp;path&nbsp;means&nbsp;"no&nbsp;sections". &nbsp;&nbsp;&nbsp;&nbsp;NSFetchedResultsController&nbsp;*aFetchedResultsController&nbsp;=&nbsp;[[NSFetchedResultsController&nbsp;alloc]&nbsp;initWithFetchRequest:fetchRequest&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;managedObjectContext:self.managedObjectContext&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sectionNameKeyPath:nil&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cacheName:nil]; &nbsp;&nbsp;&nbsp;&nbsp;aFetchedResultsController.delegate&nbsp;=&nbsp;self; &nbsp;&nbsp;&nbsp;&nbsp;[fetchRequest&nbsp;release]; &nbsp;&nbsp;&nbsp;&nbsp;NSError&nbsp;*error&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(![aFetchedResultsController&nbsp;performFetch:&error])&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Replace&nbsp;this&nbsp;implementation&nbsp;with&nbsp;code&nbsp;to&nbsp;handle&nbsp;the&nbsp;error&nbsp;appropriately. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;abort()&nbsp;causes&nbsp;the&nbsp;application&nbsp;to&nbsp;generate&nbsp;a&nbsp;crash&nbsp;log&nbsp;and&nbsp;terminate.&nbsp;You&nbsp;should&nbsp;not&nbsp;use&nbsp;this&nbsp;function&nbsp;in&nbsp;a&nbsp;shipping&nbsp;application,&nbsp;although&nbsp;it&nbsp;may&nbsp;be&nbsp;useful&nbsp;during&nbsp;development.&nbsp;If&nbsp;it&nbsp;is&nbsp;not&nbsp;possible&nbsp;to&nbsp;recover&nbsp;from&nbsp;the&nbsp;error,&nbsp;display&nbsp;an&nbsp;alert&nbsp;panel&nbsp;that&nbsp;instructs&nbsp;the&nbsp;user&nbsp;to&nbsp;quit&nbsp;the&nbsp;application&nbsp;by&nbsp;pressing&nbsp;the&nbsp;Home&nbsp;button. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSLog(@"Unresolved&nbsp;error&nbsp;%@,&nbsp;%@",&nbsp;error,&nbsp;[error&nbsp;userInfo]); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;abort(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;aFetchedResultsController;}&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;(NSFetchedResultsController&nbsp;*)fetchedResultsController&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(fetchedResultsController_&nbsp;!=&nbsp;nil)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;fetchedResultsController_; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;fetchedResultsController_&nbsp;=&nbsp;[self&nbsp;newFetchedResultsControllerWithSearch:nil]; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[[fetchedResultsController_&nbsp;retain]&nbsp;autorelease];}&nbsp;&nbsp;&nbsp;-&nbsp;(NSFetchedResultsController&nbsp;*)searchFetchedResultsController&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(searchFetchedResultsController_&nbsp;!=&nbsp;nil)&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;searchFetchedResultsController_; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;searchFetchedResultsController_&nbsp;=&nbsp;[self&nbsp;newFetchedResultsControllerWithSearch:self.searchDisplayController.searchBar.text]; &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;[[searchFetchedResultsController_&nbsp;retain]&nbsp;autorelease];}

梦里花落0921

有人评论说,这可以用一个单独完成NSFetchedResultsController。这就是我所做的,这里是细节。此解决方案假设您只想过滤表格并维护搜索结果的所有其他方面(排序顺序,单元格布局等)。首先,在UITableViewController子类中定义两个属性(使用适当的@synthesize和dealloc,如果适用):@property&nbsp;(nonatomic,&nbsp;retain)&nbsp;UISearchDisplayController&nbsp;*searchController;@property&nbsp;(nonatomic,&nbsp;retain)&nbsp;NSString&nbsp;*searchString;其次,初始化子类viewDidLoad:方法中的搜索栏UITableViewController:UISearchBar&nbsp;*searchBar&nbsp;=&nbsp;[[UISearchBar&nbsp;alloc]&nbsp;initWithFrame:CGRectMake(0,0,self.tableView.frame.size.width,44)];&nbsp;searchBar.placeholder&nbsp;=&nbsp;@"Search";searchBar.delegate&nbsp;=&nbsp;self;self.searchController&nbsp;=&nbsp;[[[UISearchDisplayController&nbsp;alloc]&nbsp;initWithSearchBar:searchBar&nbsp;contentsController:self]&nbsp;autorelease];self.searchController.delegate&nbsp;=&nbsp;self;self.searchController.searchResultsDataSource&nbsp;=&nbsp;self;&nbsp;&nbsp;&nbsp;self.searchController.searchResultsDelegate&nbsp;=&nbsp;self;&nbsp;self.tableView.tableHeaderView&nbsp;=&nbsp;self.searchController.searchBar;[searchBar&nbsp;release];第三,实现这样的UISearchDisplayController委托方法://&nbsp;This&nbsp;gets&nbsp;called&nbsp;when&nbsp;you&nbsp;start&nbsp;typing&nbsp;text&nbsp;into&nbsp;the&nbsp;search&nbsp;bar-(BOOL)searchDisplayController:(UISearchDisplayController&nbsp;*)_controller&nbsp;shouldReloadTableForSearchString:(NSString&nbsp;*)_searchString&nbsp;{ &nbsp;&nbsp;&nbsp;self.searchString&nbsp;=&nbsp;_searchString; &nbsp;&nbsp;&nbsp;self.fetchedResultsController&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;return&nbsp;YES;}//&nbsp;This&nbsp;gets&nbsp;called&nbsp;when&nbsp;you&nbsp;cancel&nbsp;or&nbsp;close&nbsp;the&nbsp;search&nbsp;bar-(void)searchDisplayController:(UISearchDisplayController&nbsp;*)controller&nbsp;willUnloadSearchResultsTableView:(UITableView&nbsp;*)tableView&nbsp;{ &nbsp;&nbsp;&nbsp;self.searchString&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;self.fetchedResultsController&nbsp;=&nbsp;nil; &nbsp;&nbsp;&nbsp;[self.tableView&nbsp;reloadData];}最后,在fetchedResultsController方法中更改NSPredicate依赖if&nbsp;self.searchString是否定义:-(NSFetchedResultsController&nbsp;*)fetchedResultsController&nbsp;{ &nbsp;&nbsp;&nbsp;if&nbsp;(fetchedResultsController&nbsp;==&nbsp;nil)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;removed&nbsp;for&nbsp;brevity &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSPredicate&nbsp;*predicate; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(self.searchString)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;predicate&nbsp;that&nbsp;uses&nbsp;searchString&nbsp;(used&nbsp;by&nbsp;UISearchDisplayController) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;e.g.,&nbsp;[NSPredicate&nbsp;predicateWithFormat:@"name&nbsp;CONTAINS[cd]&nbsp;%@",&nbsp;self.searchString]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predicate&nbsp;=&nbsp;...&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;predicate&nbsp;=&nbsp;...&nbsp;//&nbsp;predicate&nbsp;without&nbsp;searchString&nbsp;(used&nbsp;by&nbsp;UITableViewController) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;removed&nbsp;for&nbsp;brevity &nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;return&nbsp;fetchedResultsController;}
打开App,查看更多内容
随时随地看视频慕课网APP