لماذا لا تطلق uisearchdisplayController طريقة DeSselectRowatIndexPath؟
سؤال
أواجه مشكلة غريبة عند البحث في UITableView باستخدام uisearchDisplayController. إن UableViewController عبارة عن فئة فرعية من UlitableViewController آخر مع طريقة DeSelectRowatIndexPath تعمل. دون البحث في معالجة وحدة التحكم ، فإن إرسال اختيارات بشكل جيد ، وإرسال مكالمة DeSelectRowatIndexPath ، ولكن إذا اخترت خلية عند البحث في الفئة الفائقة ، لا يتلقى الخلية سوى تسليط الضوء على الخلية. فيما يلي الرمز من الفئة الفرعية الخاصة بي.
@implementation AdvancedViewController
@synthesize searchDisplayController, dict, filteredList;
- (void)viewDidLoad {
[super viewDidLoad];
// Programmatically set up search bar
UISearchBar *mySearchBar = [[UISearchBar alloc] init];
mySearchBar.delegate = self;
[mySearchBar setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[mySearchBar sizeToFit];
self.tableView.tableHeaderView = mySearchBar;
// Programmatically set up search display controller
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:mySearchBar contentsController:self];
[self setSearchDisplayController:searchDisplayController];
[searchDisplayController setDelegate:self];
[searchDisplayController setSearchResultsDataSource:self];
// Parse data from server
NSData * jsonData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
NSArray * items = [[NSArray alloc] initWithArray:[[CJSONDeserializer deserializer] deserializeAsArray:jsonData error:nil]];
// Init variables
dict = [[NSMutableDictionary alloc] init];
listIndex = [[NSMutableArray alloc] init];
fullList = [[NSMutableArray alloc] init];
filteredList = [[NSMutableArray alloc] init];
// Get each item and format it for the UI
for(NSMutableArray * item in items) {
// Get the first letter
NSString * firstKey = [[[item objectAtIndex:0] substringWithRange:NSMakeRange(0,1)] uppercaseString];
// Put symbols and numbers in the same section
if ([[firstKey stringByTrimmingCharactersInSet:[[NSCharacterSet letterCharacterSet] invertedSet]] isEqualToString:@""]) firstKey = @"#";
// If there isn't a section with this key
if (![listIndex containsObject:firstKey]) {
// Add the key to the index for faster access (because it's already sorted)
[listIndex addObject:firstKey];
// Add the key to the unordered dictionary
[dict setObject:[NSMutableArray array] forKey:firstKey];
}
// Add the object to the dictionary
[[dict objectForKey:firstKey] addObject:[[NSMutableDictionary alloc] initWithObjects:item forKeys:[NSArray arrayWithObjects:@"name", @"url", nil]]];
// Add the object to the list for simple searching
[fullList addObject:[[NSMutableDictionary alloc] initWithObjects:item forKeys:[NSArray arrayWithObjects:@"name", @"url", nil]]];
}
filteredList = [NSMutableArray arrayWithCapacity:[fullList count]];
}
#pragma mark -
#pragma mark Table view data source
// Custom method for object oriented data access
- (NSString *)tableView:(UITableView *)tableView dataForRowAtIndexPath:(NSIndexPath *)indexPath withKey:(NSString *)key {
return (NSString *)((tableView == self.searchDisplayController.searchResultsTableView) ?
[[filteredList objectAtIndex:indexPath.row] objectForKey:key] :
[[[dict objectForKey:[listIndex objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row] valueForKey:key]);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return (tableView == self.searchDisplayController.searchResultsTableView) ? 1 : (([listIndex count] > 0) ? [[dict allKeys] count] : 1);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return (tableView == self.searchDisplayController.searchResultsTableView) ? [filteredList count] : [[dict objectForKey:[listIndex objectAtIndex:section]] count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return (tableView == self.searchDisplayController.searchResultsTableView) ? [[NSArray alloc] initWithObjects:nil] : listIndex;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return (tableView == self.searchDisplayController.searchResultsTableView) ? @"" : [listIndex objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *kCellID = @"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString * name = nil;
// TODO: Make dataForRowAtIndexPath work here
if (tableView == self.searchDisplayController.searchResultsTableView) {
// NOTE: dataForRowAtIndexPath causes this to crash for some unknown reason. Maybe it is called before viewDidLoad and has no data?
name = [[filteredList objectAtIndex:indexPath.row] objectForKey:@"name"];
} else {
// This always works
name = [self tableView:[self tableView] dataForRowAtIndexPath:indexPath withKey:@"name"];
}
cell.textLabel.text = name;
return cell;
}
#pragma mark Search Methods
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
// Clear the filtered array
[self.filteredList removeAllObjects];
// Filter the array
for (NSDictionary *item in fullList) {
// Compare the item's name to the search text
NSComparisonResult result = [[item objectForKey:@"name"] compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame) {
// Add to the filtered array if it matches
[self.filteredList addObject:item];
}
}
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope: [[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void)viewDidUnload { filteredList = nil; }
@end
المحلول
نصيحتي هي الحفاظ على ملف UITableView
خاصية في وحدة تحكم العرض الخاصة بك تسمى currentTableView
. عندما يتغير نص حقل البحث ، قمنا بتعيين قيمة هذه الخاصية:
- (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString searchScope:(NSInteger)searchOption {
...
if ([[searchString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length])
self.currentTableView = searchDisplayController.searchResultsTableView;
else
self.currentTableView = tableView;
...
}
يمكن لجميع الطرق الأخرى اختبار ما إذا كانت currentTableView
هو عرض جدول نتائج البحث أو عرض الجدول "العادي". يمكن أن تعمل وحدة تحكم النتائج التي تم إحضارها معها currentTableView
بغض النظر عن السياق في. إلخ.
نصائح أخرى
حدثت لي نفس المشكلة ، لقد ارتكبت نفس الخطأ معك. نسيت أن تضيف searchResultsDelegate
. يتم حل مشكلتي عن طريق تغيير التعليمات البرمجية كما هو موضح أدناه:
يضيف
[searchDisplayController setSearchResultsDelegate:self];
أقل
[searchDisplayController setDelegate:self];
[searchDisplayController setSearchResultsDataSource:self];