سؤال

أواجه مشكلة غريبة عند البحث في 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];
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top