iOS search bar not showing results

2019-03-01 15:28发布

问题:

*Update: This actually works, the style for my custom cell hasn't come across and so the cell looks blank. How then do I get the searchResultsTableView to use my custom cell?

I have implemented a search bar in my table view. Searching, filtering all work when I debug, but when I enter characters into the search bar, the results do not load or show. This is everything I'm doing:

@interface InviteTableViewController ()<UIAlertViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>

@property(nonatomic, strong) NSNumber *contactsCount;
@property(nonatomic, strong) InviteTableViewCell *selectedCell;

@property(strong, nonatomic) NSMutableArray *filteredContactArray;
@property (weak, nonatomic) IBOutlet UISearchBar *contactsSearchBar;
@end

@implementation InviteTableViewController

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

- (void) extractAllContacts: (ABAddressBookRef) addressBookRef{
    NSMutableArray *contactsArray = [NSMutableArray array];
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
    CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBookRef);

    for(int i = 0; i < numberOfPeople; i++){
        ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
        NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
        if(firstName){
        ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);

        for (CFIndex i = 0; i < ABMultiValueGetCount(emails); i++) {
            NSString *email = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(emails, i);
            MyUser *amUser = [[MyUser alloc] init];
            amUser.email =email;

            NSString *fullName =[NSString stringWithFormat:@"%@ %@",firstName, (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty))];
            amUser.fullName = fullName;
            [contactsArray addObject:amUser];
        }

        }

    }

    NSLog(@"================================count ============= %d", [contactsArray count]);
    contactsArray = [contactsArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
        NSDate *first = [(MyUser*) a fullName];
        NSDate *second = [(MyUser*)b fullName];
        return [first compare:second];
    }];
    self.inviteContactsArray = contactsArray;
    self.filteredContactArray = [NSMutableArray arrayWithCapacity:[contactsArray count]];

    [self.tableView reloadData];


}

- (void)viewDidLoad
{
    [super viewDidLoad];  

    _contactsCount = [NSNumber numberWithInt:0];


    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);

    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                [self extractAllContacts: addressBookRef];
                [self.tableView reloadData];
            } else {
                NSString *message = [NSString stringWithFormat:@"You have not given permission to use your address book.  Please allow in settings "];
                UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Enable Contacts" message:message delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];

                [alert show];
            }
        });
    }
    else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
        // The user has previously given access, add the contact
        [self extractAllContacts:addressBookRef];
    }
    else {
        // The user has previously denied access
        // Send an alert telling user to change privacy setting in settings app
    }

[self.tableView reloadData];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [self.filteredContactArray count];
    } else {
        return [self.inviteContactsArray count];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{


    static NSString *CellIdentifier = @"InviteCell";

    InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if ( cell == nil ) {
        cell = [[InviteTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    MyUser *person = nil;

    if (tableView == self.searchDisplayController.searchResultsTableView)
    {

        person = [self.filteredContactArray objectAtIndex:[indexPath row]];
        NSMutableArray *tempArray = self.filteredContactArray;

    }
    else
    {
        person = [self.inviteContactsArray objectAtIndex:[indexPath row]];
    }




    //InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    person = [self.inviteContactsArray objectAtIndex:indexPath.row];

    cell.nameLabel.text = person.fullName;
    cell.emailLabel.text = person.email;

    return cell;

}




#pragma mark Content Filtering
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {


    // Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array
    [self.filteredContactArray removeAllObjects];
    // Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.fullName contains[c] %@",searchText];
    self.filteredContactArray = [NSMutableArray arrayWithArray:[self.inviteContactsArray filteredArrayUsingPredicate:predicate]];


}

#pragma mark - UISearchDisplayController Delegate Methods

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                      objectAtIndex:[self.searchDisplayController.searchBar
                                                     selectedScopeButtonIndex]]];

    return YES;
}


@end

This is what it looks like:

回答1:

Agree with @rdelmar.

BUT There is a kind of tricky behavior in TableView, if you change the code in

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ....
    InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    ....
}

to

InviteTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if added the prefix "self." your code should works fine.

and

if ( cell == nil )
 {
    cell = [[InviteTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
 }

is unnecessary. it will just create a standard "Subtitle Cell" for you that seems not you want, just remove them.



回答2:

If you want to use the same cell for your main table and the search results table, you should make the cell in a xib (or you could do it entirely in code). In viewDidLoad, register the nib for both table views,

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.searchDisplayController.searchResultsTableView registerNib:[UINib nibWithNibName:@"InviteTableViewCell" bundle:nil] forCellReuseIdentifier:@"InviteCell"];
    [self.tableView registerNib:[UINib nibWithNibName:@"InviteTableViewCell" bundle:nil] forCellReuseIdentifier:@"inviteCell"];
}

In cellForRowAtIndexPath, you can do something like this,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"InviteCell" forIndexPath:indexPath];
    MyUser *person = ([tableView isEqual:self.tableView])? self.inviteContactsArray[indexPath.row] : self.filteredContactArray[indexPath row];
    cell.nameLabel.text = person.fullName;
    cell.emailLabel.text = person.email;
    return cell;
}

If you've already setup your cell in the storyboard, you can copy and paste it into an empty xib file, so you don't have to set it up all over again. You can delete the cell from your storyboard table view since you will be getting the cell from the xib file instead.



回答3:

Below line in viewdidload should do the trick

self.searchDisplayController.searchResultsTableView.rowHeight = self.tableView.rowHeight