Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

trey5498

macrumors regular
Original poster
Jun 16, 2008
191
0
I am trying to set up a UIPickerView with a UISearchBar that will help to find the info of states. I have the UIPickerView working beautifully. However, I can not get the searchbar to function with the picker. I have set the Searchbar delegate to the main controller.


Here is the code that is supposed to do it, I know at the moment it is filtering and removing some (would like it to just jump to the correct name as I type it without filtering). This doesn't update. Can anyone direct me to how to finish this out and how to correctly jump to the state without filtering?

This is for Xcode 5 IOS 7

The Array ListOfStates is the filtered array

and States is the main array


Code:
(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 1;
}

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    
    if (searching) {
        return _ListOfStates.count;
    }else{
        return _States.count;
    }
    
}

#pragma mark Picker Delegate Methods

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    
    if (searching) {
       
        return [_ListOfStates objectAtIndex:row];
    } else {
        
        return [_States objectAtIndex:row];
        
    }
}

(void)searhBar:(UISearchBar *)SearchBar textDidChange:(NSString *) searchText {
    
    [_ListOfStates removeAllObjects];
        
        if (searchText.length == 0) {
            searching = NO;
        } else {
            searching = YES;
            
           
            
            for (NSString *StateName in _States) {
                NSRange stateNameRange = [StateName rangeOfString:searchText options:NSCaseInsensitiveSearch];
                
                if (stateNameRange.location != NSNotFound) {
                    [_ListOfStates addObject:StateName];
                }
            }
            
        }
        
        [_StatePickerView reloadAllComponents];
   
}
 
Last edited:
(would like it to just jump to the correct name as I type it without filtering). This doesn't update.

Are you saying that the picker view doesn't update? or it doesn't just jump to the right one? Is this because there are multiple items that contain the search string?

Edit: do you make sure to set up the pickerView DataSource and Delegate as your view controller?
 
I did set up the data source and the delegate to the view controller. As far as just having the App function as a UIPickerView example, it works perfectly.

The issue is solely with the UISearchBar. I know it can work with UITableView, and I have seen it in other Apps work with UIPickerViews. However, in my case, not only does the UIPickerView NOT update with the filtered array, I have no idea how to leave the original array alone and just simply jump to the one I am searching for.

It shouldnt be that much extra coding to make it work, I just am at a loss.
 
Update:

I have gotten it to update with the filtered array correctly now. I corrected a typo and moved the reload call up. So when you type "N" only the states that begin with "N" will show up.

Now I have to figure out how to keep the array untouched and just jump to the letters you begin to type. Any idea how to do that?

Here is the updated code:

Code:
- (void)searchBar:(UISearchBar *)SearchBar textDidChange:(NSString *) searchText {
    
    [_ListOfStates removeAllObjects];
    if (searchText.length == 0) {
        searching = NO;
    } else {
        searching = YES;
        
        for (NSString *StateName in _States) {
            NSRange stateNameRange = [StateName rangeOfString:searchText options:NSCaseInsensitiveSearch];
            
            if (stateNameRange.location != NSNotFound) {
                [_ListOfStates addObject:StateName];
                [_StatePickerView reloadAllComponents];
            }
        }
            
    }
        
    [_StatePickerView reloadAllComponents];
}
 
maybe something like this?

Code:
- (void)searchBar:(UISearchBar *)SearchBar textDidChange:(NSString *) searchText {
    

    if (searchText.length == 0) {
        searching = NO;
    } else {
        searching = YES;
        int i = 0;
        int locatedIndex = -1;
        for (NSString *StateName in _States) {
            NSRange stateNameRange = [StateName rangeOfString:searchText options:NSCaseInsensitiveSearch];
            
            if (stateNameRange.location != NSNotFound) {
                locatedIndex = i;
            }
           i++;
        }
            
    }

    if (locatedIndex > -1) {
       [_StatePickerView selectRow:locatedIndex inComponent:0 animated:YES];
    }
        
}

edit: you probably want to setup the loop so that you break out after finding a matching string
 
That did the trick. I have a few other things I need to make it work perfectly with what I want, but that is it ;)

The other thing that just came up is I decided to use the PList to help keep track of all the information instead of large amounts of arrays.

Here is what I got:

Code:
NSString *StatePath = [[NSBundle mainBundle] pathForResource:@"States" ofType:@"plist"];

NSDictionary *StateDictionary = [[NSDictionary alloc] initWithContentsOfFile:StatePath];

_States = StateDictionary[@"States"];

Now the array populates just fine, but I am not sure how to pull it out with the pickerview. I thought maybe:

Code:
return [_States objectAtIndex:row[@"StateName"];

Here is an example of the plist:

Code:
<dict>
	<key>States</key>
	<array>
		<dict>
			<key>StateName</key>
			<string>Alabama</string>
			<key>Est</key>
			<string>1819</string>
			<key>Cap</key>
			<string>Montgomery</string>
			<key>Pop</key>
			<string>4822023</string>
			<key>Large</key>
			<string>Birmingham</string>
		</dict>
.................

and pushing to a label for the Capital would look like:

Code:
CapitalTextLabel.text = _States[indexPath.row][@"Cap"];
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.