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
}
Related
How can I import all the contacts from the phone book in your application. and so that we could gain the imported contacts.
Andrei brother if you have not got answer still,I give you answer.I tried and got the solution.It works fine.
The AddressBookUI framework is deprecated in iOS 9, so we need to use Contact Framework.
First I set or hook up the tableView using XIB or Storyboard for showing contacts.
Must import the Contacts framework
ViewController.h
#import <UIKit/UIKit.h>
#import <Contacts/Contacts.h>
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
{
}
#property (strong, nonatomic) IBOutlet UITableView *tableViewShowContacts;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *arrayContacts;
}
#end
#implementation ViewController
#synthesize tableViewShowContacts;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arrayContacts = [[NSMutableArray alloc]init];
[self getAuthorizationandContact];
//Register the cell
[tableViewContactData registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
[self.view addSubview:tableViewShowContacts];
}
-(void)fetchContactsandAuthorization
{
// Request authorization to Contacts
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
UIImage *profileImage;
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
for (CNContact *contact in cnContacts)
{
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:#"person-icon.png"];
}
for (CNLabeledValue *label in contact.phoneNumbers)
{
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,#"fullName",profileImage,#"userImage",phone,#"PhoneNumbers", nil];
[arrayContacts addObject:[NSString stringWithFormat:#"%#",[personDict objectForKey:#"fullName"]]];
NSLog(#"The contacts are - %#",arrayContacts);
}
dispatch_async(dispatch_get_main_queue(), ^{
[tableViewShowContacts reloadData];
});
}
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return arrayContacts.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *strCell = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:strCell];
if(cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strCell];
}
cell.textLabel.text = arrayContacts[indexPath.row];
return cell;
}
The printed results of Contacts are
The contacts are - (
"John Appleseed",
"Kate Bell",
"Anna Haro",
"Daniel Higgins",
"David Taylor",
"Hank Zakroff"
)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
i have following code in viewdidload
totalstring=[[NSMutableArray alloc]initWithObjects:#"a",#"b",#"c",#"d",#"e",#"f",#"g",#"h",#"i",#"j",#"k",#"l",#"m",#"n",#"n",#"o",#"p",#"q",#"r",#"s",#"s",#"t",#"u",#"v",#"w",#"x",#"y",#"z", nil];
indid=indidvalue1;
NSLog(#"the ind id value is %#",indid);
serviceCall=[[Services alloc]init];
NSString *contactsDisplay1=#"ContactDetails";
NSDictionary *contactsDisplayDetails1 =#{#"IND_ID":indid};
[serviceCall ContactsDisplayUrl:contactsDisplay1 ContactsDisplayDetails:contactsDisplayDetails1];
[serviceCall setDelegate:self];
code for implimenting search bar
{
filteredstring =[[NSMutableArray alloc]init];
for (NSString *str in totalstring )
{
NSRange stringrange =[str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(stringrange.location!= NSNotFound)
{
[filteredstring addObject:str];
}
}
}
[tableView reloadData];
code for table view
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [searchResultsArray objectAtIndex:indexPath.row];
} else
{
UIFont *myfont=[UIFont fontWithName:#"Arial" size:35];
cell.textLabel.text = [contactNameSplitDisplayArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text=[relationTypeSplitDisplayArray objectAtIndex:indexPath.row];
cell.textLabel.font=myfont;
}
return cell;
How can i implement search bar in table view for contacts in story board ?I am new to iOS
?
and how to implement plus button and dots button within the table view?
Devi my complete answer.It works perfectly.I use search bar.Also use that delegate methods.
ViewController.h
#import <UIKit/UIKit.h>
#import <Contacts/Contacts.h> //Must import contact framework
#interface ViewController : UIViewController<UISearchBarDelegate,UITableViewDataSource,UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *searchbarContacts;
#property (strong, nonatomic) IBOutlet UITableView *tableViewContactData;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *arrayTableData;
NSMutableArray *arraySearchContactData;
}
#end
#implementation ViewController
#synthesize tableViewContactData;
#synthesize searchbarContacts;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arrayTableData = [[NSMutableArray alloc]init];
arraySearchContactData = [[NSMutableArray alloc]init];
[self fetchContactsandAuthorization];
[tableViewContactData registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
[self.view addSubview:tableViewContactData];
}
//Fetching Contact and Authorization access
-(void)fetchContactsandAuthorization
{
// Request authorization to Contacts
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
UIImage *profileImage;
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
for (CNContact *contact in cnContacts)
{
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:#"person-icon.png"];
}
for (CNLabeledValue *label in contact.phoneNumbers)
{
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,#"fullName",profileImage,#"userImage",phone,#"PhoneNumbers", nil];
[arrayTableData addObject:[NSString stringWithFormat:#"%#",[personDict objectForKey:#"fullName"]]];
[arraySearchContactData addObject:[NSString stringWithFormat:#"%#",[personDict objectForKey:#"fullName"]]];
NSLog(#"The contactsArray are - %#",arrayTableData);
}
dispatch_async(dispatch_get_main_queue(), ^{
[tableViewContactData reloadData];
});
}
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return arrayTableData.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *strCell = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:strCell];
if(cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strCell];
}
cell.textLabel.text = arrayTableData[indexPath.row];
return cell;
}
#pragma mark - SearchBar Delegate Methods
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
#try
{
[arrayTableData removeAllObjects];
stringSearch = #"YES";
NSString *name = #"";
if ([searchText length] > 0)
{
for (int i = 0; i < [arraySearchContactData count] ; i++)
{
name = [arraySearchContactData objectAtIndex:i];
if (name.length >= searchText.length)
{
NSRange titleResultsRange = [name rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
[arrayTableData addObject:[arraySearchContactData objectAtIndex:i]];
}
}
}
}
else
{
[arrayTableData addObjectsFromArray:arraySearchContactData];
}
[tableViewContactData reloadData];
}
#catch (NSException *exception) {
}
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)SearchBar
{
SearchBar.showsCancelButton=YES;
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)theSearchBar
{
[theSearchBar resignFirstResponder];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)SearchBar
{
#try
{
SearchBar.showsCancelButton=NO;
[SearchBar resignFirstResponder];
[tableViewContactData reloadData];
}
#catch (NSException *exception) {
}
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)SearchBar
{
[SearchBar resignFirstResponder];
}
#end
The Printed results For Contacts
The contactsArray are - (
"John Appleseed",
"Kate Bell",
"Anna Haro",
"Daniel Higgins",
"David Taylor",
"Hank Zakroff"
)
Please Refer the below link, i can able to implement the search bar in table view by using this.
http://www.appcoda.com/search-bar-tutorial-ios7/
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]
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.
I'm following this AppCoda tutorial on implementing Search; however, I'm pulling titles for the table view from Parse and can't get the search function to work. Throws an exception when I start typing in the search:
'Can't use in/contains operator with collection {
buildingLat = "42.726366";
buildingLong = "-84.480642";
buildingTitle = "International Center";
} (not a collection)'
Here's the code for my table view controller:
#import "BuildingsViewController.h"
#import <Parse/Parse.h>
#interface BuildingsViewController ()
#end
#implementation BuildingsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self performSelector:#selector(retrieveBuildings)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - TableView Setup
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.buildingsArray count];
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.searchResults count];
} else {
return [self.buildingsArray count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"buildingsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
PFObject *tempObject = [self.buildingsArray objectAtIndex:indexPath.row];
cell.textLabel.text = [tempObject objectForKey:#"buildingTitle"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [tempObject objectForKey:#"buildingTitle"];
}
return cell;
}
#pragma mark - Helper Methods
-(void)retrieveBuildings
{
PFQuery *retrieveBuildings = [PFQuery queryWithClassName:#"buildingsList"];
[retrieveBuildings findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.buildingsArray = [[NSArray alloc] initWithArray:objects];
}
[self.tableView reloadData];
}];
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
self.searchResults = [self.buildingsArray filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
I think you are on the right track...
My understanding is that you are receiving an array of dictionaries, and passing that received array to your declared buildingsArray. This is not the issue. The issue in my understanding is that you are then attempting to retrieve one of the values from one of those dictionaries without the appropriate code.
Your are attempting this process in two locations.
I refer to the code within your cellForRowAtIndexPath method.
As an aside, it is no longer necessary to check for cell == nil, so you can remove the if statement that wraps your cell setter (cell = [[UITableViewCell...).
UPDATE...
The crash in your code when you remove this check for nil is due to the fact that you do not register a reuse identifier for the searchResultsTableView.
To correct your search and data parsing, I recommend that you follow the sample code I have included following.
Add a new property tempMutableArray, and remove the static declaration from cellForRowAtIndexPath and place it between the #import and #interface lines as shown following...
#import <Parse/Parse.h>
static NSString *CellIdentifier = #"buildingsCell"; // relocated static declaration
#interface BuildingsViewController ()
#property (nonatomic, strong) NSMutableArray *tempMutableArray;
#end
// implementation
Then in your viewDidLoad TVC lifecycle method, instantiate the NSMutableArray, and register the UITableViewCell class and CellIdentifier reuse identifier with searchResultsTableView...
- (void)viewDidLoad {
[super viewDidLoad];
//...your other code...
[self setTempMutableArray:[[NSMutableArray alloc] init]];
[self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:CellIdentifier];
}
...
YOUR NEW REPLACEMENT cellForRowAtIndexPath: METHOD
To properly parse your information from Parse, try the following...
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell = [self.searchDisplayController.searchResultsTableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *tempDict = nil;
NSString *tempString = nil;
tempDict = [self.buildingsArray objectAtIndex:indexPath.row];
tempString = [tempDict objectForKey:#"buildingTitle"];
[cell.textLabel setText:tempString];
}
return cell;
}
You will also need to complete similar in your filterContentForSearchText: method.
YOUR NEW REPLACEMENT filterContentForSearchText: METHOD
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = nil;
[self.tempMutableArray removeAllObjects];
for (NSDictionary *tempDict in self.buildingsArray) {
NSString *tempString = nil;
tempString = [tempDict objectForKey:#"buildingTitle"];
[self.tempMutableArray addObject:tempString];
}
resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchText];
self.searchResults = [self.tempMutableArray filteredArrayUsingPredicate:resultPredicate];
}
...CONTINUE WITH PREVIOUS RESPONSE
My understanding... what is happening in your code is that your PFQuery returns an NSArray in its completion block. You set your property buildingsArray, also an NSArray, based on this. Your no longer need, as far as I understand, to treat the returned data as a PFObject.
Let me know how you go.
You are trying to apply the NSPredicate on an array of PFObjects so your predicate needs to look like this:
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"variableNameToSearchOn contains[cd] %#",
searchText];
EDIT:
You can try this:
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"buildingTitle contains[c] %#",
searchText];
#pragma mark UISearchBarDelegate
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
sar.showsCancelButton=YES;
sar.autocorrectionType = UITextAutocorrectionTypeNo;
}
- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
NSString* newText = [searchBar.text stringByReplacingCharactersInRange:range withString:text];
searchStr = newText;
[self DisplayMatchSearch];
[tblView reloadData];
return YES;
}
-(BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar{
//write code for requset data from database search.....
sar.showsCancelButton=NO;
[sar resignFirstResponder];
return YES;
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
[self getAlldata];
#try {
[tblBeepUsers reloadData];
}
#catch (NSException * e) {
}
[sar resignFirstResponder];
sar.text=#"";
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
searchStr = sar.text;
[sar resignFirstResponder];
[self DisplayMatchSearch];
[tblView reloadData];
}
-(void)DisplayMatchSearch{
if (searchStr && searchStr.length) {
//temp array
arrLocation = [[NSMutableArray alloc] init];
//parsed array self.buildingsArray
for (NSDictionary *dictionary in self.buildingsArray)
{
if ([[dictionary objectForKey:#"name"] rangeOfString:searchStr options:NSCaseInsensitiveSearch].location != NSNotFound) {
[arrLocation addObject:dictionary];
}
}
[tblview reloadData];
}
}