I've made a view for editing friend, with a searchbar. My adding/deleting friends is working fine, but I've a problem with my adding/deleting friends WITH SEARCHBAR...
My searchbar finds well the email I'm tapping, but the order change :
if I find 2 email with my searchbar, the 2 email will are the 2 first email in my property "Allfriend", and not the email I found with searchbar...
Is there any code to complete in didSelectRowAtIndexPath after NSLog ?
I let you see my code, tell me if you see a problem :
editfriend.h :
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface EditFriendsViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>
#property (nonatomic, strong) NSArray *allUsers;
#property (nonatomic, strong) PFUser *currentUser;
#property (nonatomic, strong) NSMutableArray *friends;
#property (strong, nonatomic) NSArray *searchResults;
#property (nonatomic, strong) PFUser *user;
#property (nonatomic, strong) NSMutableArray *filteredArray;
#property (nonatomic, strong) UIImage *MindleNav;
-(BOOL)isFriend:(PFUser*)user;
#end
editfriend.m :
#import "EditFriendsViewController.h"
#interface EditFriendsViewController ()
#end
#implementation EditFriendsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:self.MindleNav];
self.searchResults = [[NSArray alloc] init];
PFQuery *query = [PFUser query];
[query orderByAscending:#"email"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
self.allUsers = objects;
// self.user = [objects objectAtIndex:0];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}];
self.currentUser = [PFUser currentUser];
}
#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.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else
{
return [self.allUsers count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [[self.searchResults objectAtIndex:indexPath.row] email];
} else {
cell.textLabel.text = user.email;
}
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
PFRelation *friendsRelation = [self.currentUser relationforKey:#"friendsRelation"];
//Edit Friends with searchbar
if (tableView == self.searchDisplayController.searchResultsTableView) {
PFUser *user = [self.searchResults objectAtIndex:indexPath.row];
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryNone;
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
for(PFUser *friend in self.searchResults) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject:friend];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.friends addObject:user];
[friendsRelation addObject:user];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
[self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
//Edit Friends
} else {
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryNone;
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject:friend];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[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
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"email beginswith[c] %#", searchText];
self.searchResults = [self.allUsers filteredArrayUsingPredicate:predicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (BOOL)isFriend:(PFUser *)user {
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
return YES;
}
}
return NO;
}
#end
You're calling [self.tableView reloadData] on a background thread (due to findObjectsInBackground), so your UI won't update right away.
If you want the changes to take place instantly, you need to rewrite that line to:
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
Also, since you already do a query for all objects in viewDidLoad, when the user would like to search, you shouldn't query again, but instead have a property called filteredUsers, which holds the user you'd like to display.
You can filter an array with:
self.filteredArray = [self.allUsers filteredArrayUsingPredicate:predicate];
You can take a look here on how to create an NSPredicate.
Related
I'm trying to do a search function in my table view, to return objects from my Parse.com class.
I'm getting this error when I try to make a search in the UISearchBar:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier FeaturedTableViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
Here's how I'm doing it:
#interface DiscoverViewController () <UISearchBarDelegate, UISearchDisplayDelegate>
#property (nonatomic, retain) PFQuery *query;
#property (nonatomic, retain) PFObject *category;
#end
#implementation DailyDiscoverViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.delegate = self;
self.searchResults = [NSMutableArray array];
_categories = [[NSMutableArray alloc] initWithCapacity:100];
}
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName:#"Projects"];
[query whereKeyExists:#"name"];
[query whereKey:#"name" containsString:searchTerm];
NSArray *results = [query findObjects];
[self.searchResults addObjectsFromArray:results];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)refresh {
PFQuery *query = [PFQuery queryWithClassName:#"Categories"];
[query orderByDescending:#"name"];
[query findObjectsInBackgroundWithBlock:^(NSArray *posts, NSError *error) {
if (!error) {
//NSLog(#"%#", posts);
} else {
}
[_categories setArray:posts];
[self.tableView reloadData];
[_loadingView stopAnimating];
[_refreshControl endRefreshing];
}];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
if (section == 0) {
return 1;
} else {
return self.categories.count;
}
} else {
return self.searchResults.count;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return 320;
} else {
return 52;
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
_featuredObject = [_featured objectAtIndex:indexPath.row];
DiscoverFeaturedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DiscoverFeaturedTableViewCell" forIndexPath:indexPath];
[(PFFile*)_featuredObject[#"picture"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
cell.image1.image = [UIImage imageWithData:data];
}];
return cell;
} else {
_category = [_categories objectAtIndex:indexPath.row];
DiscoverTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DiscoverTableViewCell" forIndexPath:indexPath];
cell.name.text = _category[#"name"];
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
PFUser *obj2 = [self.searchResults objectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:#"Projects"];
PFObject *searchedUser = [query getObjectWithId:obj2.objectId];
NSString *first = [searchedUser objectForKey:#"name"];
cell.name.text = [first substringToIndex:1];
cell.name.text = first;
return cell;
}
return cell;
}
}
#end
I think you can look this stack over flow post : POST
K.
Ok,
Try it on viewDidLoad:
YourCustomCell *yourCustomCell = [UINib
nibWithNibName:#"YourCustomCell" bundle:nil]; [self.tableView
registerNib:cellNib forCellReuseIdentifier:#"cell"];
Note: Your custom cell must have a .xib of course.
You could try this, I remember running into this exact issue and this was one of the solutions I tried:
[self.tableView registerClass:[DiscoverTableViewCell class] forCellReuseIdentifier:#"DiscoverTableViewCell"];
However, I distinctly remember that this didn't work. It turned out I hadn't correctly connected the cells in the storyboard. Furthermore, make sure that the class of your storyboard cell has been changed to represent your cell's custom class.
I am trying to make an ios app on xcode by following this - http://www.appcoda.com/search-bar-tutorial-ios7/. When I type in search bar everything works in console but output is not getting displayed on the screen
#interface AllUseraStatusViewController ()
#property (weak, nonatomic) IBOutlet UITableView *statusText;
#property (weak, nonatomic) IBOutlet UITableView *statusTime;
#property (weak, nonatomic) IBOutlet UITableView *statusUserName;
#property (strong,nonatomic) NSArray *statusList;
#property (strong,nonatomic) NSMutableArray *allStatusLists;
#property(strong,nonatomic) NSArray *searchResults;
#property(strong,nonatomic) PFObject *object;
#end
#implementation AllUseraStatusViewController
- (void)viewDidLoad {
[super viewDidLoad];
PFQuery *query = [PFQuery queryWithClassName:#"Status"];
[query includeKey:#"user"];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// 3
if (!error){
self.statusList = objects;
[self.tableView reloadData];
} else {
// 4
[[[UIAlertView alloc] initWithTitle:#"Error" message:[error userInfo][#"error"] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(tableView==self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}else{
return [self.statusList count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier= #"AllUsersStatusCell";
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell==nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView){
self.object =[self.searchResults objectAtIndex:indexPath.item];
NSLog(#"THIS IS object %#",self.object);
}else{
self.object =[self.statusList objectAtIndex:indexPath.item];
}
NSLog(#"THIS IS objectttt %#",self.object); <--this prints correct status in console
UILabel *statusText = (UILabel *)[cell viewWithTag:100];
[statusText setText:[self.object objectForKey:#"status"]];
NSLog(#"THIS IS objectttt %#",statusText);<--but this prints null in console
UILabel *statusTime = (UILabel *)[cell viewWithTag:101];
[statusTime setText:[[self.object createdAt] description]];
UILabel *statusUserName = (UILabel *)[cell viewWithTag:102];
PFUser *userName = [self.object objectForKey:#"user"];
[statusUserName setText:userName.username];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UserProfileViewController *vc = segue.destinationViewController;
PFObject *object = [self.statusList objectAtIndex:indexPath.row];
vc.statusObject=object;
}
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForTextSearch:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
-(void)filterContentForTextSearch:(NSString *)searchText scope:(NSString *)scope
{
NSPredicate *resultPredicate=[NSPredicate predicateWithFormat:#"status contains[c] %#",searchText];
NSLog(#"THIS IS %#",resultPredicate);
self.searchResults = [self.statusList filteredArrayUsingPredicate:resultPredicate];
NSLog(#"THIS IS THE %#", self.searchResults);
}
#end
MAKING THE ERROR MORE CLEAR
This is the error in the above code
NSLog(#"THIS IS object %#",self.object);// this prints correct object
UILabel *statusText = (UILabel *)[cell viewWithTag:100];
[statusText setText:[self.object objectForKey:#"status"]];
NSLog(#".....THIS IS objectt %#",statusText.text);// it prints null on console
NSLog(#".....THIS IS objectttt %#",[self.object objectForKey:#"status"]);// this prints correct o/p
I have a view controller that retrieves address information from my web service, stores it in a mutable array and then displays each address in a table view. I have a search bar on the same view controller that i'd like to search through each of the addresses and display the results. I have this working with a test NSArray, however I'm not sure what I need to do to the filterContentForSearchText function to get it to search through an NSMutableArray. Any help appreciated.
Object Class
// Branches.h
#interface Branches : NSObject
#property (nonatomic, retain) NSString *BranchAddress;
#end
View Controller Class
// ViewController.h
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
.
// ViewController.m
#import "AFHTTPRequestOperationManager.h"
#import "ViewController.h"
#import "Branches.h"
#interface ViewController () {
NSMutableArray *array;
}
#property (strong, nonatomic) NSArray *searchResults;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize myArray
array = [[NSMutableArray alloc] init];
// Set POST parameters
NSDictionary *parameters = #{#"key" : #"value"};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:#"webservice_address" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Check to see if responseObject contains data
if (responseObject != nil) {
// Loop through JSON
for (NSDictionary *dictionary in responseObject) {
// Initialize object
Branches *branches = [[Branches alloc] init];
branches.branchAddress = [dictionary objectForKey:#"Object"];
// Add object to myArray
[array addObject:branches];
[self.tableView reloadData];
}
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
#pragma Table View Methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.searchResults count];
} else {
return [array count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [[array objectAtIndex:indexPath.row] BranchAddress];
}
return cell;
}
#pragma Search Methods
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSArray *masterArray = array;
NSArray *searchResults = [masterArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Branches *evaluatedObject, NSDictionary *bindings) {
//NSLog(#"%#", evaluatedObject.BranchAddress);
return ([evaluatedObject.BranchAddress rangeOfString: searchText options:NSCaseInsensitiveSearch].location != NSNotFound);
}]];
NSLog(#" %i", searchResults.count);
//[searchResults removeAllObjects];
//[searchResults addObjectsFromArray:searchResults];
//reload after this
NSLog(#"%#", [searchResults objectAtIndex:0]);
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
u can try this
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSArray *masterArray = self.array;
NSArray *resultsArray = [masterArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Branches *evaluatedObject, NSDictionary *bindings) {
return ([evaluatedObject.BranchAddress rangeOfString: searchText options:NSCaseInsensitiveSearch].location != NSNotFound);
}]];
//edited
[self.searchResults removeAllObjects]; //self.searchResults should be mutable array
[self.searchResults addObjectsFromArray:resultsArray];//put the new values to searchResults
//after this self.searchResults contains objects of filtered Branches u can get the values for example
NSLog(#"%#", [[self.searchResults objectAtIndex:0] BranchAddress]);//self.searchResults contains objects of Branches not the string itself
//reload after this
}
I've made a view for editing friends with search bar. Everything works fine, but when I find users with search bar, cell.accessoryType isn't right. (My cell.accessoryType is good when I don't use search bar).
Checkmark isn't for the right user.
I think it's a problem in "isFriend" action ?
Here is my code :
editfriends.h :
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface EditFriendsViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>
#property (nonatomic, strong) NSArray *allUsers;
#property (nonatomic, strong) PFUser *currentUser;
#property (nonatomic, strong) NSMutableArray *friends;
#property (strong, nonatomic) NSArray *searchResults;
#property (nonatomic, strong) PFUser *user;
#property (nonatomic, strong) UIImage *MindleNav;
-(BOOL)isFriend:(PFUser*)user;
#end
editfriends.m :
#import "EditFriendsViewController.h"
#interface EditFriendsViewController ()
#end
#implementation EditFriendsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:self.MindleNav];
self.searchResults = [[NSArray alloc] init];
PFQuery *query = [PFUser query];
[query orderByAscending:#"email"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
self.allUsers = objects;
// self.user = [objects objectAtIndex:0];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}];
self.currentUser = [PFUser currentUser];
}
#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.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else
{
return [self.allUsers count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [[self.searchResults objectAtIndex:indexPath.row] email];
} else {
cell.textLabel.text = user.email;
}
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
PFRelation *friendsRelation = [self.currentUser relationforKey:#"friendsRelation"];
//Edit Friends with searchbar
if (tableView == self.searchDisplayController.searchResultsTableView) {
PFUser *user = [self.searchResults objectAtIndex:indexPath.row];
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryNone;
for(PFUser *friend in self.searchResults) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject:friend];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.friends addObject:user];
[friendsRelation addObject:user];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
[self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
//Edit Friends
} else {
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
if ([self isFriend:user ]) {
cell.accessoryType = UITableViewCellAccessoryNone;
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject:friend];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[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
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"email beginswith[c] %#", searchText];
self.searchResults = [self.allUsers filteredArrayUsingPredicate:predicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (BOOL)isFriend:(PFUser *)user {
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
return YES;
}
}
return NO;
}
#end
It would appear to be because you're using the wrong user object to check the status. Compare with:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSArray *sourceData = (tableView == self.searchDisplayController.searchResultsTableView ? self.searchResults : self.allUsers);
PFUser *user = [sourceData objectAtIndex:indexPath.row];
cell.textLabel.text = user.email;
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
I've made a view for editing friend, with a searchbar. My adding/deleting friends is working fine, but I've a problem with my adding/deleting friends WITH SEARCHBAR...
My searchbar finds well the email I'm tapping, but the order change :
if I find 2 email with my searchbar, the 2 email will are the 2 first email in my property "Allfriend", and not the email I found with searchbar...
Is there any code to complete in didSelectRowAtIndexPath after NSLog ?
I let you see my code, tell me if you see a problem :
editfriend.h :
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface EditFriendsViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>
#property (nonatomic, strong) NSArray *allUsers;
#property (nonatomic, strong) PFUser *currentUser;
#property (nonatomic, strong) NSMutableArray *friends;
#property (strong, nonatomic) NSArray *searchResults;
#property (nonatomic, strong) PFUser *user;
#property (nonatomic, strong) NSMutableArray *filteredArray;
#property (nonatomic, strong) UIImage *MindleNav;
-(BOOL)isFriend:(PFUser*)user;
#end
editfriend.m :
#import "EditFriendsViewController.h"
#interface EditFriendsViewController ()
#end
#implementation EditFriendsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:self.MindleNav];
self.searchResults = [[NSArray alloc] init];
PFQuery *query = [PFUser query];
[query orderByAscending:#"email"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
self.allUsers = objects;
// self.user = [objects objectAtIndex:0];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}];
self.currentUser = [PFUser currentUser];
}
#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.
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResults count];
}
else
{
return [self.allUsers count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [[self.searchResults objectAtIndex:indexPath.row] email];
} else {
cell.textLabel.text = user.email;
}
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
PFRelation *friendsRelation = [self.currentUser relationforKey:#"friendsRelation"];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSLog(#"CLICK search");
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
NSLog(#"CLICK");
}
if ([self isFriend:user]) {
cell.accessoryType = UITableViewCellAccessoryNone;
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
[self.friends removeObject:friend];
break;
}
}
[friendsRelation removeObject:user];
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[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
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"email beginswith[c] %#", searchText];
self.searchResults = [self.allUsers filteredArrayUsingPredicate:predicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (BOOL)isFriend:(PFUser *)user {
for(PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
return YES;
}
}
return NO;
}
#end
Your array (probably) contains PFUser objects and the predicate is:
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", searchText]
BEGINSWITH works only for strings and you try to apply it to PFUser objects. This is a reason of the crash. If you want to search for users whose names begin with the searchText, change the predicate to:
[NSPredicate predicateWithFormat:#"username beginswith[c] %#", searchText]