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
Jack Ryder
7,286 PointsRibbit search friends feature
Hi, I've had a look at various posts such as this https://teamtreehouse.com/forum/please-help-search-feature-for-ribbit
I still can't get the search to return any users, if anyone could look at my code and help me out, I would be extremely thankful!
the header file:
'''objective-c
import <UIKit/UIKit.h>
import <Parse/Parse.h>
@interface EditFriendsViewController : UITableViewController <UISearchBarDelegate> @property (nonatomic, strong) NSArray *allUsers; @property (nonatomic, strong) PFUser *currentUser; @property (nonatomic, strong) NSMutableArray *friends; @property (nonatomic, strong) PFUser *user;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
- (BOOL) isFriend:(PFUser *)user;
@end
'''
and here's the implementation file:
'''objective-c
import "EditFriendsViewController.h"
import "MSCellAccessory.h"
@interface EditFriendsViewController ()
@end
@implementation EditFriendsViewController
UIColor *disclosureColor;
-
(void)viewDidLoad { [super viewDidLoad]; PFQuery *query = [PFUser query]; [query orderByAscending:@"username"]; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { if (error) { NSLog(@"%@ %@", error, [error userInfo]); } else { self.allUsers = objects; [self.tableView reloadData]; } }];
self.currentUser = [PFUser currentUser];
disclosureColor = [UIColor colorWithRed:0.553 green:0.439 blue:0.718 alpha:1.0];
self.searchBar.delegate = self;
}
-
(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];
self.tableView.dataSource = nil; }
pragma mark - Table view data source
-
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections. return 1; }
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section. return [self.allUsers count]; }
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row]; cell.textLabel.text = self.user.username;
if ([self isFriend:user]) { cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor]; } else { cell.accessoryView = nil; }
return cell; }
-
(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:NO]; // use to deselect a row
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row]; PFRelation *friendsRelation = [self.currentUser relationForKey:@"friendsRelation"];
if ([self isFriend:user]) { cell.accessoryView = nil;
for (PFUser *friend in self.friends) { if ([friend.objectId isEqualToString:user.objectId]) { [self.friends removeObject: friend]; break; } } [friendsRelation removeObject:user];
} else { cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor]; [self.friends addObject:user]; [friendsRelation addObject:user];
}
[self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) { if (error) { NSLog(@" error: %@ %@", error, [error userInfo]); } }];
}
pragma mark - Helper Methods
-
(BOOL) isFriend:(PFUser *)user {
for (PFUser *friend in self.friends) { if ([friend.objectId isEqualToString:user.objectId]) { return YES; } } return NO; }
-
(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard [self.searchBar resignFirstResponder];
}
-
(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
//Enable the cancel button when the user touches the search field self.searchBar.showsCancelButton = TRUE; }
-
(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
//dsiable the cancel button when the user ends editing self.searchBar.showsCancelButton = FALSE; }
-
(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard [self.searchBar resignFirstResponder];
//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) { //found a user //set the user as the table views data source and reload the table view self.user = [objects objectAtIndex:0]; //A user was not found, display error message } else { //no user found } [self.tableView reloadData]; } else { //error occurred } }];
}
} @end
'''
thanks!
7 Answers
Stone Preston
42,016 Pointsyou set your user property to the object returned by the query here:
//found a user
//set the user as the table views data source and reload the table view
self.user = [objects objectAtIndex:0];
however your tableView is set to get its data from your allUsers property in your tableView delegate methods. So basically in your cellForRowAtIndexPath and numberOfRowsInSection you need to replace self.allUsers with self.user
Jack Ryder
7,286 Pointsgot it sorted, cheers!
POKE !
88 PointsHow did you solve it? This is my code and I have the same error
<p>#import "FindViewController.h"
#import "FindDetailsViewController.h"
#import "FindCell.h"
@interface FindViewController ()
@end
@implementation FindViewController {
//
CLLocationManager *locationManager;
}
@synthesize currentGeoPoint;
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
//Sök
self.searchBar.delegate = self;
//Hittar GeoLocation för telefonen
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
NSLog(@"%@", [self deviceLocation]);
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.opaque = NO;
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"berg.jpg"]];
self.navigationItem.hidesBackButton = YES;
UIImage *image = [UIImage imageNamed: @"Invest.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage: image];
self.navigationItem.titleView = imageView;
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.opaque = NO;
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"berg.jpg"]];
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(refreshTable:)
name:@"refreshTable"
object:nil];
}
- (NSString *)deviceLocation {
return [NSString stringWithFormat:@"latitude: %f longitude: %f", locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"refreshTable" object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)loadObjects
{
if (!self.currentGeoPoint)
{
[PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geo, NSError *error)
{
self.currentGeoPoint = geo;
[super loadObjects];
}];
}
else
{
[super loadObjects];
}
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFUser query];
query.limit = 3;
[query whereKey:@"money" equalTo: [NSNumber numberWithBool:TRUE]];
[query whereKey:@"currentLocation" nearGeoPoint:self.currentGeoPoint withinKilometers:20];
return query;
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
// The number of objects to show per page
self.objectsPerPage = 10;
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = @"FindCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:@"profileimageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"placeholder2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:@"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:@"title"];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(@"error: %@", [error localizedDescription]);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"showFindDetails"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
FindDetailsViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
FindCell *find = [[FindCell alloc] init];
find.name = [object objectForKey:@"name"];
find.imageFile = [object objectForKey:@"profileimageFile"];
find.prepTime = [object objectForKey:@"title"];
find.location = [object objectForKey:@"location"];
find.ingredients = [object objectForKey:@"moneyProfile"];
destViewController.find= find;
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard
[self.searchBar resignFirstResponder];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
//Enable the cancel button when the user touches the search field
self.searchBar.showsCancelButton = TRUE;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
//dsiable the cancel button when the user ends editing
self.searchBar.showsCancelButton = FALSE;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard
[self.searchBar resignFirstResponder];
//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) {
//found a user
//set the user as the table views data source and reload the table view
//A user was not found, display error message
} else {
//no user found
}
[self.tableView reloadData];
} else {
//error occurred
}
}];
}
}
@end</p>
```
Stone Preston
42,016 PointsSince you are using the PFQuery tableViewController it might not work as you want it to. Im not sure, ive never used one of those. The tutorial and code I wrote assumes you are just using a normal tableViewController, not one of Parse's custom classes.
see the selected best answer for this post. your issue is here:
if (objects.count > 0) {
//found a user
//set the user as the table views data source and reload the table view
}
you need to create a property to store the object that was found by the query and set its value in that if block. You also need to make sure you tableView delegate methods use that newly create property as their data source. The code you are using does indeed find a user, its just you havent properly told your table what to do with it. ill add a line to the code so you can see what I mean:
if (objects.count > 0) {
//found a user
//set the user as the table views data source and reload the table view
self.user = [objects objectAtIndex:0];
}
now once the query runs we have a user property that gets set with the value of the object that the query found.
then you just need to make sure you edit your tableView delegate methods to use this self.user property:
Jack Ryder
7,286 Pointshaving issues adding friends with the search bar, every friend that i add is the current user instead of the user that i've selected despite the user not showing up at all in search results.
#import "EditFriendsViewController.h"
#import "MSCellAccessory.h"
@interface EditFriendsViewController ()
@end
@implementation EditFriendsViewController
UIColor *disclosureColor;
- (void)viewDidLoad
{
[super viewDidLoad];
PFQuery *query = [PFUser query];
[query orderByAscending:@"username"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(@"%@ %@", error, [error userInfo]);
}
else {
self.allUsers = objects;
[self.tableView reloadData];
}
}];
self.currentUser = [PFUser currentUser];
disclosureColor = [UIColor colorWithRed:0.553 green:0.439 blue:0.718 alpha:1.0];
self.searchBar.delegate = self;
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.user = nil;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
//[self.allUsers count];
if (self.user) {
//a user was found, we need to display one row.
return 1;
} else {
//a user was not found/searched for yet, dont display any rows
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = self.user; //objectAtIndex:indexPath.row];
cell.textLabel.text = self.user.username;
if ([self isFriend:user]) {
cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor];
}
else {
cell.accessoryView = nil;
}
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
// use to deselect a row
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
PFRelation *friendsRelation = [self.currentUser relationForKey:@"friendsRelation"];
if ([self isFriend:user]) {
cell.accessoryView = nil;
for (PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject: friend];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor];
[self.friends addObject:user];
[friendsRelation addObject:user];
}
[self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(@" error: %@ %@", error, [error userInfo]);
}
}];
}
#pragma mark - Helper Methods
- (BOOL) isFriend:(PFUser *)user {
for (PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId])
{
return YES;
}
}
return NO;
}
- (IBAction)backButton:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard
[self.searchBar resignFirstResponder];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
//Enable the cancel button when the user touches the search field
self.user = nil;
[self.tableView reloadData];
self.searchBar.showsCancelButton = TRUE;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
//dsiable the cancel button when the user ends editing
self.searchBar.showsCancelButton = FALSE;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard
[self.searchBar resignFirstResponder];
//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) {
//found a user
//set the user as the table views data source and reload the table view
self.user = [objects objectAtIndex:0];
//A user was not found, display error message
} else {
//no user found
}
[self.tableView reloadData];
} else {
//error occurred
}
}];
}
}
@end
Jack Ryder
7,286 Pointssolved! forgot to change self.allUsers in didSelectRowAtIndexPath too!
POKE !
88 PointsCould you please your final h and m file to help a fellow out Jack Ryder :)
Jack Ryder
7,286 Points#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
@interface EditFriendsViewController : UITableViewController <UISearchBarDelegate>
@property (nonatomic, strong) NSArray *allUsers;
@property (nonatomic, strong) PFUser *currentUser;
@property (nonatomic, strong) NSMutableArray *friends;
@property (nonatomic, strong) PFUser *user;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
- (BOOL) isFriend:(PFUser *)user;
implementation file:
@interface EditFriendsViewController ()
@end
@implementation EditFriendsViewController
UIColor *disclosureColor;
- (void)viewDidLoad {
[super viewDidLoad];
PFQuery *query = [PFUser query];
[query orderByAscending:@"username"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(@"%@ %@", error, [error userInfo]);
}
else {
self.allUsers = objects;
[self.tableView reloadData];
}
}];
self.currentUser = [PFUser currentUser];
disclosureColor = [UIColor colorWithRed:0.553 green:0.439 blue:0.718 alpha:1.0];
self.searchBar.delegate = self;
//self.textField.delegate = self;
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.user = nil;
}
#pragma mark - Table view data source
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
//[self.allUsers count];
if (self.user) {
//a user was found, we need to display one row.
return 1;
} else {
//a user was not found/searched for yet, dont display any rows
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = self.user; //[self.allUsers objectAtIndex:indexPath.row];
cell.textLabel.text = self.user.username;
if ([self isFriend:user]) {
cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor];
}
else {
cell.accessoryView = nil;
}
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
// use to deselect a row
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
PFUser *user = self.user;
PFRelation *friendsRelation = [self.currentUser relationForKey:@"friendsRelation"];
if ([self isFriend:user]) {
cell.accessoryView = nil;
for (PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject: friend];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryView = [MSCellAccessory accessoryWithType:FLAT_CHECKMARK color:disclosureColor];
[self.friends addObject:user];
[friendsRelation addObject:user];
}
[self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(@" error: %@ %@", error, [error userInfo]);
}
}];
}
#pragma mark - Helper Methods
- (BOOL) isFriend:(PFUser *)user {
for (PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId])
{
return YES;
}
}
return NO;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard
[self.searchBar resignFirstResponder];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
//Enable the cancel button when the user touches the search field
self.user = nil;
[self.tableView reloadData];
self.searchBar.showsCancelButton = TRUE;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
//dsiable the cancel button when the user ends editing
self.searchBar.showsCancelButton = FALSE;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
//dismiss keyboard
[self.searchBar resignFirstResponder];
//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) {
//found a user
//set the user as the table views data source and reload the table view
self.user = [objects objectAtIndex:0];
//A user was not found, display error message
} else {
//no user found
}
[self.tableView reloadData];
} else {
//error occurred
}
}];
}
}
@end
POKE !
88 PointsThanks man :)
Zachary Zhao
4,705 PointsJack Ryder even though this was from a long time ago, it still worked amazingly for me on iOS9. Thanks for the awesome work! :))
Jack Ryder
7,286 PointsJack Ryder
7,286 PointsThanks for the help, which parts of those methods do i need to input self.user?
Thanks