I'm working on a project and I want the user to be able to search a list on a UITableView. I've added the search bar and connected it to the search display controller. I have no idea how to actually search the list and grab the data from parse, filter it, set it to the PFUser of toUser, and display it. Anyone know how to do this?
Here's the code where I save the message:
if (toUser!= nil){
app[#"toUser"]=toUser;
}
[app save];
Here are some code snippets for the table view:
This displays the users and filters out the current user:
ParseExampleAppDelegate *delegate=[[UIApplication sharedApplication] delegate];
PFQuery *query = [PFUser query];
users = [[query findObjects] mutableCopy];
for(PFUser *user in users){
if ([user.objectId isEqualToString:delegate.applicationUser.objectId]){
[users removeObject:user];
break;
}
}
[users removeObject:delegate.applicationUser];
NSLog(#"all user: %lu",users.count);
[self.usersTable setDelegate:self];
[self.usersTable setDataSource:self];
[self.usersTable reloadData];
[self.usersTable reloadData];
Some methods for the table view:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"userCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
PFObject *tempObject = [users objectAtIndex:indexPath.row];
cell.text= [tempObject objectForKey:#"username"];
return cell;
NSMutableArray *filteredStrings;
BOOL isFiltered;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"users:%lu",[users count]);
return [users count];
}
Thanks for your help,
armanb21
Related
I am attempting to work a segmented control to display data from a search into categories. However although data is received it is not being displayed on my table. Here is my code for the two View Controllers. The child View controller is the one in which the UITableView is stored.
PARENT VC
- (void)searchPeople:(NSString*)text {
if(![text isEqualToString:#""]){
PFQuery *userWithName = [PFQuery queryWithClassName:#"_User"];
[userWithName whereKey:#"fullName" containsString:text];
PFQuery *userWithHandle = [PFQuery queryWithClassName:#"_User"];
[userWithHandle whereKey:#"username" containsString:text];
PFQuery *userQuery = [PFQuery orQueryWithSubqueries:#[userWithHandle,userWithName]];
[userQuery findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
NSLog(#"USERS: %#",results);
[self.userResults removeAllObjects];
[self.userResults addObjectsFromArray:results];
[[ArrayManager sharedInstance].searchResults addObjectsFromArray:results];
NSLog(#"Count Number: %#", [ArrayManager sharedInstance].searchResults);
[[NSNotificationCenter defaultCenter] postNotificationName:#"reload_data" object:self];
}];
}
}
CHILD VC
-(void)handle_data {
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Object Entries: %lu", (unsigned long)[[ArrayManager sharedInstance].searchResults count]);
NSMutableArray * array = [[ArrayManager sharedInstance] getGlobalArray];
return [array count];
}
- (void)tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *data = [[ArrayManager sharedInstance]init].searchResults[indexPath.row];
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
}
cell.textLabel.text = data[#"objectId"];
return cell;
}
Data is returned fine from the server however, there is no data being displayed on the table. The ArrayManager class is a Singleton class.
Create a Data Access Object (DAO) and store all information in an array in that.
http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
Have both VC's change and access the DAO instead of each other. It is much simpler that way.
I'm building an app that retrieves items from a Parse database and inserts them into a UITableView. In my Parse database, each item has its own date (i.e. film dates). Now this is the part I’m having trouble with:
I would like to sort the items by their own date, with the date for that item being in the section header. I would also like to show only the items whose date is from the current date and onwards. Please also know that I’m using the latest version of iOS and using Objective-C. I have exhausted other sources but have yet to find exactly what I need. Any guidance will be greatly appreciated!
Right now I have this in my ShowsTableViewController.m:
My getShows method:
-(void)getShows{
PFQuery *retrieveShows = [PFQuery queryWithClassName:#"shows"];
[retrieveShows findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError
*error) {
//NSLog(#"%#", objects);
if (!error)
{
_showsArray = [[NSArray alloc] initWithArray:objects];
}
[showsTableView reloadData];
}];
}
And this is how I'm currently populating the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ShowsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"showsCell" forIndexPath:indexPath];
PFObject *tempObject = [_showsArray objectAtIndex:indexPath.row];
cell.cellTitle.text = [tempObject objectForKey:#"title];
return cell;
}
With you require, I think you have to sort your data and put it in to a Array. And this Array will hold list of Dictionary. Each Dictionary will have two key (first key is title: and value of it is title you want show to header, second key is data: and value of it is array item in seciton)
And now you will implement UITableViewDataSource for it:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.listData count];
}
for each section you can implement same like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *data = [[self.listData objectAtIndex:section] objectForKey:#"data"];
}
And show header:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[self.listData objectAtIndex:section] objectForKey:#"title"];
}
And show to cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ShowsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"showsCell" forIndexPath:indexPath];
PFObject *tempObject = [[self.listData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.cellTitle.text = [tempObject objectForKey:#"title];
return cell;
}
You can do this way to achieve what you want.
I am working with parse on a little app. It should show names, where stored on parse user class in an Array column.
Here is my Code:
#synthesize friendsList;
-(void)viewDidLoad{
[super viewDidLoad];
PFQuery*query = [PFUser query];
[query getObjectInBackgroundWithId:#"myObjectId" block:^(PFObject *gameScore, NSError *error) {
if(error==nil){
friendsList = [gameScore valueForKey:#"Friends"];
NSLog(#"%#", friendsList);
}
else{
NSLog(#"Error");
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [friendsList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell" forIndexPath:indexPath];
cell.textLabel.text = friendsList[indexPath.row];
return cell;
}
The problem is, when I am loading the data from parse. It does't show anything on the table view.
Do I declare friendsList likt this:
friendsList = [NSMutableArray arrayWithObjects:#"Name1", #"Name2", nil];
It will work.
Your tableView is blank as your friendsList is not populated when the tableView is displayed.
In the completion block reload the tableView.
In your completion block after friendsList = [gameScore valueForKey:#"Friends"]; statement add following code:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData]; // assuming your table view is tableView
});
Hope this helps!
I think you missed allocating the array
friendsList = [[NSMutableArray alloc] init];
I have a problem with my TableViewController. There is a custom cell, with a class, and various infos dynamically loaded. My TableViewController appears, but my cell doesn't display, but i can touch this, and my transition with infos are good.
Thanks for your answers.
TableViewController.m
#interface Chat() {
NSMutableArray *messages;
UIRefreshControl *refreshControl;
}
#property (strong, nonatomic) IBOutlet UITableView *tableMessages;
#end
#implementation Chat
NSString *cellIdentifier = #"ChatCell";
- (void)viewDidLoad {
[super viewDidLoad];
[_tableMessages registerClass:[ChatCell class] forCellReuseIdentifier:cellIdentifier];
refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(loadMessages) forControlEvents:UIControlEventValueChanged];
[_tableMessages addSubview:refreshControl];
messages = [[NSMutableArray alloc] init];
[self loadMessages];
}
- (void)loadMessages {
if ([PFUser currentUser] != nil)
{
PFQuery *query = [PFQuery queryWithClassName:PF_MESSAGES_CLASS_NAME];
[query whereKey:PF_MESSAGES_USER equalTo:[PFUser currentUser]];
[query includeKey:PF_MESSAGES_LASTUSER];
[query orderByDescending:PF_MESSAGES_UPDATEDACTION];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error == nil) {
[messages removeAllObjects];
[messages addObjectsFromArray:objects];
[_tableMessages reloadData];
} else [ProgressHUD showError:#"Network error."];
[refreshControl endRefreshing];
}];
}
}
- (void)actionCleanup {
[messages removeAllObjects];
[_tableMessages reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ChatCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[cell bindData:messages[indexPath.row]];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
DeleteMessageItem(messages[indexPath.row]);
[messages removeObjectAtIndex:indexPath.row];
[_tableMessages deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PFObject *message = messages[indexPath.row];
ChatView *chatView = [[ChatView alloc] initWith:message[PF_MESSAGES_ROOMID]];
[self.navigationController pushViewController:chatView animated:YES];
}
#end
TableViewCell.m
#interface ChatCell() {
PFObject *message;
}
#end
#implementation ChatCell
- (void)bindData:(PFObject *)message_ {
message = message_;
_chatImg.layer.cornerRadius = _chatImg.frame.size.width/2;
_chatImg.layer.masksToBounds = YES;
PFUser *lastUser = message[PF_MESSAGES_LASTUSER];
[_chatImg setFile:lastUser[PF_USER_PICTURE]];
[_chatImg loadInBackground];
_chatUsername.text = message[PF_MESSAGES_DESCRIPTION];
_chatMessage.text = message[PF_MESSAGES_LASTMESSAGE];
NSTimeInterval seconds = [[NSDate date] timeIntervalSinceDate:message.updatedAt];
_chatDate.text = TimeElapsed(seconds);
}
#end
It's because you register the cell using - registerClass:forCellReuseIdentifier:.
If you register it this way you have to construct the view programmatically or load the nib file in ChatCell code.
To solve the problem, do either of these:
Create a nib file containing the view for your table view cell and set the class to ChatCell. Then use - registerNib:forCellReuseIdentifier: to register the nib.
Construct the view programmatically eg. create a UILabel and add it as a subview of ChatCell.
Make the prototype cell in the storyboard and set the cell identifier to ChatCell. Then remove the - registerClass:forCellReuseIdentifier:
Check You are given correct cell Identifier in storyboard. (case sensitive) " ChatCell"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ChatCell";
ChatCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[cell bindData:messages[indexPath.row]];
return cell;
}
You are updating the UI on background thread. Try this, in your "loadMessages" method.
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
//update UI here
if (error == nil) {
[messages removeAllObjects];
[messages addObjectsFromArray:objects];
[_tableMessages reloadData];
} else [ProgressHUD showError:#"Network error."];
[refreshControl endRefreshing];
});
}];
I have this code:
for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
I have a search bar that filters out search objects and puts a check mark on the cell when you click it. However, if you search and click on the first cell, it checks it off. But if you delete the search text, the check mark shows up on the first cell, not the one that I checked off. Here is a video showing this:
https://docs.google.com/file/d/0B1Of4oDADQCQZkF0aGdhdmF0VjA/edit
Where do I put the code above in the code below so that the checkmark stays with the selected cell?
#import "MSAddFriendsViewController.h"
#interface MSAddFriendsViewController ()
#end
#implementation MSAddFriendsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
PFQuery *query = [PFUser query];
[query orderByAscending:#"username"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error %#, %#", error, [error userInfo]);
}
else {
self.allUsers = objects;
[self.tableView reloadData];
}
}];
self.currentUser = [PFUser currentUser];
self.searchUsers.delegate = self;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (searchText.length == 0) {
self.userResults = nil;
[self.tableView reloadData];
return ;
}
self.userResults = [NSMutableArray array];
for (PFUser *user in self.allUsers) {
if ([user.username rangeOfString:searchText
options:(NSAnchoredSearch | NSCaseInsensitiveSearch)].location == 0) {
[self.userResults addObject:user];
}
}
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
if (self.userResults != nil) {
return [self.userResults count];
}
// 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;
if (self.userResults != nil) {
user = [self.userResults objectAtIndex:indexPath.row];
} else {
user = [self.allUsers objectAtIndex:indexPath.row];
}
cell.textLabel.text = user.username;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
PFRelation *friendsRelation = [self.currentUser relationforKey:#"friendsRelation"];
PFUser *user = [self.allUsers objectAtIndex:indexPath.row];
[friendsRelation addObject:user];
[self.currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(#"Error %# %#", error, [error userInfo]);
} }];
}
#end
Can someone please correct the code above?
The first block of code just deselects all of the selected rows. This isn't the solution to your problem. There are a few fundamental issues with your code in general that need correcting...
First off -- you need to keep an array of the selected cells, indexed as the full (non-searching) table is indexed. For example, if there's text in the search bar and the first row is selected, your selected cell array should also indicate the selection boolean of the preceding and following rows not currently visible, and do so all in order.
Secondly -- you need to explicitly set the checkmarks in your cells' accessory views during your cellForRowAtIndexPath: method in order to indicate your selected cells. The only reason that you have a checkmark in the first cell after the search bar is cleared and the table's reloaded is because the cell's being reused (i.e. [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]).
By fixing these first and second issues, you should be off to a good start... When you're not searching, the selected cell array should contain the appropriate selection booleans for all the cells in proper order; and when you are searching, you have to filter the selected cell array in just the same way you'd filter your table based on the search text. And instead of adding checkmarks during didSelectRowAtIndexPath:, you would be better off just indicating that the cell is selected in the selected cell array then reloading table to display the appropriate checkmark.