Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Stone Preston
Stone Preston
42,016 Points

For those of you wanting to implement the ability to search for friends in the Ribbit app, here is a step by step guide

ive posted a general way do to this before, but I decided to rewrite it into a more precise and step by step guide. I worked through the following instructions myself and was able to easily implement it in my own ribbit app following these instructions step by step. Its a very minimalist search feature that you can build more functionality to if you desire to. It will show you a user if you search for a valid username, and wont show anything if the username is invalid. So it can be done easily and without issue following these instructions (as long as your have the app working correctly to begin with).

Note: You will need to remove any code having to do with the allUsers property in your editFriendsViewController. You wont be using that property anymore (at least if you choose to implement search using this little tutorial). This also removes the ability to remove friends using the editFriendsView controller. I implemented a way of removing friends using a swipe to delete feature on the main friends view, but that wont be covered here.

The following changes need to be made to your editFriendsViewController.

first drag a search bar onto your viewController (it should drop right in near the top of the table). Ctrl click and drag to your header file and create a property called searchBar.

@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;

also add a property to store the user that is found by the search query (ill call it foundUser)

@property (nonatomic, strong) PFUser *foundUser;

Next, conform to the search bar delegate protocol:

@interface THEditFriendsViewController : UITableViewController <UISearchBarDelegate>

In your viewDidLoadMethod you need to set the search bars delegate as your viewController (self)

- (void)viewDidLoad
{

    [super viewDidLoad];

    self.searchBar.delegate = self;

}

and implement the following delegate methods:

#pragma  mark - Search Bar Delegate Methods

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {

    //dismiss keyboard and reload table
    [self.searchBar resignFirstResponder];
    [self.tableView reloadData];
}

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {

    //Enable the cancel button when the user touches the search field
    self.searchBar.showsCancelButton = TRUE;
}

- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {

    //disable the cancel button when the user ends editing
    self.searchBar.showsCancelButton = FALSE;
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {

    //dismiss keyboard
    [self.searchBar resignFirstResponder];

    //reset the foundUser property
    self.foundUser = nil;


    //Strip the whitespace off the end of the search text
    NSString *searchText = [self.searchBar.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];


    //Check to make sure the field isnt empty and Query parse for username in the text field
    if (![searchText isEqualToString:@""]) {

        PFQuery *query = [PFUser query];
        [query whereKey:@"username" equalTo:searchText];
        [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
            if (!error) {

                //check to make sure the query actually found a user
                if (objects.count > 0) {

                    //set your foundUser property to the user that was found by the query (we use last object since its an array)
                    self.foundUser = objects.lastObject;

                //The query was succesful but returned no results. A user was not found, display error message
                } else {



                }

                //reload the tableView after the user searches
                [self.tableView reloadData];

            } else {

                //error occurred with query

                }

        }];

    }


}

Thats it for the search bar, now you need to modify your tableView delegate methods:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections. If a user was found there will be one section, if not there will be 0
    if (self.foundUser) {

        return 1;

    } else {

        return 0;
    }

}

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

    // Return the number of rows in the section. If a user was found there will be one row, if not there will be 0 rows
    if (self.foundUser) {

        return 1;

    } else {

        return 0;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];


    //If a user was found
    if (self.foundUser) {

        //set the label as the foundUsers username 
        cell.textLabel.text = self.foundUser.username;


    }

    return cell;
}

you also need to make a change inside the didSelectRowAtIndexPath method (change the method to use self.foundUser instead of self.allUsers). There is a comment above the line you need to change, but ive provided the entire method for context

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    //this is the line you need to make the change to.
    PFUser *user = self.foundUser;

    PFRelation *friendsRelation = [self.currentUser relationforKey:@"friendsRelation"];

    if ([self isFriend:user]) {

        //remove them
        cell.accessoryView = nil;

        for(PFUser *friend in self.friends) {

            if([friend.objectId isEqualToString:user.objectId]) {

                [self.friends removeObject:friend];
                break;
            }
        }


        [friendsRelation removeObject:user];



    }

    else {

        //add them
        cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor];
        [self.friends addObject:user];
        [friendsRelation addObject:user];

    }

    [self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
        if (!error) {

        } else {

            NSLog(@"Error: %@ %@", error, [error userInfo]);

        }
    }];



}

and thats all it takes. Its a lot of delegate methods, but its pretty simple to understand. Obviously id probably edit the didSelectRowAtIndexPath to maybe function a bit differently than what it is now (dont really need to add check marks anymore, might as well just take the user back to the main friends view when he clicks the cell)

5 Answers

@Jack Ryder , if you want that it's simple like this

  1. clone the files of search friends and friends list
  2. make the parse create a table called something like keywords
  3. then as you watched how @Ben Jakuben make relation between users you can also make relation between users and there keywords
  4. the search will be in keywords and return the user name or anything you want depending on the keyword.
Jack Ryder
Jack Ryder
7,286 Points

Stone Preston Any idea how you would go about this if the user wanted to search for keywords instead of an exact username? cheers

Monika Kapur
Monika Kapur
1,290 Points

i want to display all users list when i m searching for the specific user and if user is found then it should show that user and when i cancel the search then it should again display all users list. How i can do that.

I don't understand when to use search bar or search bar view controller please some one clarify this question