I use this code for the Table View:
#implementation FollowerTableViewController
- (instancetype)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) { // This table displays items in the Todo class
self.parseClassName = #"FriendClass";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = YES;
self.objectsPerPage = 25;
}
return self;
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:#"to" equalTo:[PFUser currentUser]];
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query orderByDescending:#"date"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *cellIdentifier = #"cell1";
PFTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier];
}
// Configure the cell to show todo item with a priority at the bottom
cell.textLabel.text = object[#"from"];
NSLog(#"%#", object[#"from"]);
//cell.detailTextLabel.text = [NSString stringWithFormat:#"Priority: %#", object[#"priority"]];
NSLog(#"%# , %#", object[#"from"], object[#"to"]);
return cell;
}
#end
And this I uploaded before:
-(void)follow {
// suppose we have a user we want to follow
PFUser *otherUser = (PFUser *)textField.text;
NSLog(#"%#", otherUser);
// create an entry in the Follow table
PFObject *follows = [PFObject objectWithClassName:#"FriendClass"];
[follows setObject:[PFUser currentUser] forKey:#"from"];
[follows setObject:otherUser forKey:#"to"];
[follows setObject:[NSDate date] forKey:#"date"];
[follows saveInBackground];
}
any idea why it doesn't work.
Related
Explanation of what's taking place: The user has added a job as their favorite within another view. Now the user is in the Favorites tab and decides that they no longer want the job as one of their favorites anymore, so they swipe to delete the job. They tap the delete button and the errors below take place...the code works as is, but it also deletes every single job the user has saved as a favorite, instead of just deleting the one job.
My code also gives me an alert of:
Warning: A long-running operation is being executed on the main thread.
Break on warnBlockingOperationOnMainThread() to debug.
#import "JobDetailViewController.h"
#import "MyFavoritesTableViewController.h"
#import "Parse/Parse.h"
#import "Job.h"
#import "JobListViewController.h"
#interface MyFavoritesTableViewController ()
#property (nonatomic, strong) NSString *mainTitle;
#property (nonatomic, strong) NSString *subTitle;
#end
#interface MyFavoritesTableViewController ()
#end
#implementation MyFavoritesTableViewController
{}
#synthesize mainTitle;
#synthesize subTitle;
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if ([PFUser currentUser]) {
// Custom the table
// The className to query on
self.parseClassName = #"Jobs";
// The key of the PFObject to display in the label of the default cell style
self.textKey = #"Position";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 30;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)objectsWillLoad {
[super objectsWillLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.tableView reloadData];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object: (PFObject *)object
{
static NSString *myJobsTableIdentifier = #"myFavsCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:myJobsTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:myJobsTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"AppIcon.png"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *positionLabel = (UILabel*) [cell viewWithTag:101];
positionLabel.text = [object objectForKey:#"Position"];
UILabel *rotationLabel = (UILabel*) [cell viewWithTag:102];
rotationLabel.text = [object objectForKey:#"Rotation"];
UILabel *locationLabel = (UILabel*) [cell viewWithTag:103];
locationLabel.text = [object objectForKey:#"Location"];
UILabel *typeLabel = (UILabel*) [cell viewWithTag:104];
typeLabel.text = [object objectForKey:#"Type"];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDetailedView"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Job *job = [[Job alloc] init];
JobDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
job.position = [object objectForKey:#"Position"];
job.poc = [object objectForKey:#"POC"];
job.email = [object objectForKey:#"Email"];
job.phone = [object objectForKey:#"Phone"];
job.apply = [object objectForKey:#"Apply"];
job.imageFile = [object objectForKey:#"imageFile"];
job.rotation = [object objectForKey:#"Rotation"];
job.location = [object objectForKey:#"Location"];
job.type = [object objectForKey:#"Type"];
job.clearance = [object objectForKey:#"Clearance"];
job.job_description = [object objectForKey:#"Job_Description"];
job.qualifications = [object objectForKey:#"Qualifications"];
job.originalJob = object;
destViewController.job = job;
}
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([self.objects count] == indexPath.row) {
[self loadNextPage];
} else {
PFObject *photo = [self.objects objectAtIndex:indexPath.row];
NSLog(#"%#", photo);
// Do something you want after selected the cell
}
}
- (PFQuery *)queryForTable
{
PFUser *user = [PFUser currentUser];
PFRelation *relation = [user relationForKey:#"Favorites"];
PFQuery *myquery = [relation query];
if (self.pullToRefreshEnabled) {
myquery.cachePolicy = kPFCachePolicyNetworkOnly;
}
return myquery;
}
#pragma mark - DeleteJobViewDelegate
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
PFUser *user = [PFUser currentUser];
PFRelation *relation = [user relationForKey:#"Favorites"];
PFQuery *myquery = [relation query];
NSArray *array = [myquery findObjects];
for (PFObject *object in array)
{
[relation removeObject:object];
}
[user saveInBackground];
[self.tableView reloadData];
[self loadObjects];
}
#end
The problem is that you are removing all the objects from the Relation:
NSArray *array = [myquery findObjects];
for (PFObject *object in array)
{
[relation removeObject:object];
}
What your code is doing is going though your array and removing each object from the relation.
What you want to do is to delete the job for that cell only. You can get that using the indexPath:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
PFUser *user = [PFUser currentUser];
PFRelation *relation = [user relationForKey:#"Favorites"];
[relation removeObject:[self.objects objectAtIndex:indexPath.row]];
[user saveInBackground];
[self.tableView reloadData];
[self loadObjects];
}
Your second problem:
Warning: A long-running operation is being executed on the main thread. Break on warnBlockingOperationOnMainThread() to debug.
That warning is because findObjects is a synchronous call. You should use the findObjectsInBackground instead. But if you make the changes I gave above, you won't need it.
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.
This question already has an answer here:
Pass data from Parse tableview to WatchKit
(1 answer)
Closed 8 years ago.
I'm using Parse to create this table view, and am trying to figure out how to get the Parse table data into an array, so I can pass it into the WatchKit InterfaceController to show the exact same thing?
So I want to show in the WatchKit interface exactly what shows in the iPhone interface.
Here is what I have, let me know if I can add anything that would be helpful:
TableVC.m:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
self.parseClassName = #"na";
self.textKey = #"dateTime";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = NO;
}
return self;
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UILabel *homeLabel = (UILabel*) [cell viewWithTag:101];
homeLabel.text = [object objectForKey:#"test"];
UILabel *dateLabel = (UILabel*) [cell viewWithTag:102];
dateLabel.text = [object objectForKey:#"dateTime"];
return cell;
}
Parse data:
TableVC.m:
I already have the basic WatchKit files and Storyboard set up. I hard coded an array to test that it was generally working. But now I just need to get the data from Parse into there, and not sure if I need to do a query and then turn that into a public array?
EDIT:
Here is my query:
PFQuery *query2 = [PFQuery queryWithClassName:#"nba"];
[query2 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Objects 2: %#", objects);
}
} else {
// Log details of the failure
NSLog(#"Error 2: %# %#", error, [error userInfo]);
}
}];
Here is my NSLog:
NSLog(#"Objects 2: %#", objects);
Console:
2015-02-09 21:06:30.845 SimpleTable[8373:1284663] Objects 2: (
"<na: 0x7ff3f8e40880, objectId: cOrjeAmwJh, localId: (null)> {\n away = Cav;\n date = \"04/19/2015\";\n dateTime = \"April 19, 2015, 16:00\";\n gNumber = 1;\n home = Bul;\n matup = \"Ca\";\n ro = \"Ro \";\n test = \"Test 2\";\n tv = T;\n}",
If you need the array, fetch it asynchronously in a method outside of the queryForTable method, get it like this:
PFQuery *query = [self queryForTable];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// objects is the array for this table
NSMutableArray *array = [#[] mutableCopy];
for (PFObject *object in objects) {
NSLog(#"we got an object with dateTime = %#", [object objectForKey:#"dateTime"]);
[array addObject:[object objectForKey:#"dateTime"]];
// you can prove this with any of your keys: away, number, home, mat up, etc.
}
}
}];
if you just want to pass the objects into an array you can do so like this or a variation of:
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
self.someArray = [query findObjects];
return query;
}
REFERNECE
I have a parse app for iOS where it is sometimes necessary to search all the users. For some reason though, the users exist in the database but other users cannot see them in a search. I have seen no correlation between users or reason for this the only thing I'm thinking is maybe parse is not searching ALL users? Here is the code for the search
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.parseClassName = #"_User";
self.textKey = #"name";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
}
return self;
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query whereKey:#"isTeacher" equalTo:#"True"];
[query whereKey:#"schoolName" equalTo:[[PFUser currentUser] objectForKey:#"schoolName"]];
return query;
}
I'm assuming if there was a problem it would be in the above, but the rest of the code is here if need be:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
PFTableViewCell *cell = (PFTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text = [object objectForKey:#"name"];
cell.detailTextLabel.text = [object objectForKey:#"username"];
}
// Configure the cell
if (tableView == self.tableView) {
cell.textLabel.text = [object objectForKey:#"name"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
PFObject* object = self.searchResults[indexPath.row];
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.textLabel.text = [object objectForKey:#"name"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *teacherUsername = cell.textLabel.text
;
//NSLog(teacherUsername);
[[NSUserDefaults standardUserDefaults] setObject:teacherUsername forKey:#"teacherUsername"];
[self performSegueWithIdentifier:#"next" sender:self];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count;
}
}
-(void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query whereKey:#"isTeacher" equalTo:#"True"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSArray *results = [NSArray arrayWithArray:objects];
NSLog(#"%#", results);
NSLog(#"%lu", (unsigned long)results.count);
NSLog(#"results^");
[self.searchResults addObjectsFromArray:results];
NSPredicate *searchPredicate =
[NSPredicate predicateWithFormat:#"SELF.name contains[c] %#",searchTerm];
_searchResults = [NSMutableArray arrayWithArray:[results filteredArrayUsingPredicate:searchPredicate]];
[self.searchDisplayController.searchResultsTableView reloadData];
NSLog(#"%#", _searchResults);
NSLog(#"%lu", (unsigned long)_searchResults.count);
NSLog(#"search results^");
}];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Is there any reason why certain users would not show up? I have checked the obvious things, making sure the users have the same "schoolName" and "isTeacher" is true but I'm stumped. Attached is a screenshot of an example user in the parse core
The default limit for a Parse query is 100 objects so even though you expect 170 PFObjects, you need to specify that you want to receive 170+ objects from your query in order to receive them all from the query using the limit parameter, ex:
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query whereKey:#"isTeacher" equalTo:#"True"];
[query setLimit: 1000]; // <-- increase the limit up to 1000
The upper limit for the number of PFObjects a PFQuery can return though is 1000, so since you have more than 1000 users and could hypothetically need to receive more than 1000 results when performing a different query, you can do so by looping through multiple queries while utilizing an increasing skip parameter, to specify the "number of objects to skip before returning any."
So whereas that first block of code I wrote will return the first 1000 objects from that query, the next 1000 can be retrieved like so:
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query whereKey:#"isTeacher" equalTo:#"True"];
[query setLimit: 1000]; // <-- increase the limit up to 1000
[query setSkip: 1000]; // <-- skip the first 1000 already found
And generally speaking, although it's probably best to receive your results bit by bit and increment setSkip to receive more results only when you absolutely need them, you can hypothetically retrieve all the objects matching your query at once, like so:
- (void)theOriginalCallingMethod {
// Start out by fetching the maximum number of results
// from the query and start at the beginning, i.e.
// not skipping anything
[self performTeacherQueryWithLimit:1000 andSkip:0];
}
- (void)performTeacherQueryWithLimit:(int)limit andSkip:(int)skip {
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query whereKey:#"isTeacher" equalTo:#"True"];
[query setLimit: limit];
[query setSkip: skip];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// If the maximum number of objects is found, there
// may be more, so continue querying
if (objects.count == limit) {
// Perform the query using the same limit, but increase
// the skip amount by that current limit to indicate
// that the next query should skip the results we just
// found
[self performTeacherQueryWithLimit:limit andSkip:skip+limit];
}
// ...other code...
}];
}
Note: This will only work with a PFTableView as long as its paginationEnabled property is set to NO.
I am trying to search my objects on parse.com using a uisearchbar and performing 'findObjectsInBackgroundWithBlock'. I am getting the correct results in my output but they are not showing up in my table.
I was previously doing this without blocks, my code worked, it got the correct results but moved very slowly and I was getting a warning, "Warning: A long-running Parse operation is being executed on the main thread"
I had previously been using the code:
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: #"Items"];
[query whereKeyExists:#"itemName"];
[query whereKeyExists:#"itemDescription"];
[query whereKey:#"tags" containsString:searchTerm];
NSArray *results = [query findObjects];
NSLog(#"%#", results);
NSLog(#"%u", results.count);
[self.searchResults addObjectsFromArray:results];
}
So now I am trying findObjectsInBackgroundWithBlock instead, I have not worked with blocks before so this is where I need help, here is my new code:
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: #"Items"];
[query whereKey:#"tags" containsString:searchTerm];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSLog(#"%#", objects);
NSLog(#"%u", objects.count);
[self.searchResults addObjectsFromArray:objects];}];
Here is some more of my code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
NSString *uniqueIdentifier = #"cell";
HomeCell *cell = nil;
cell = (HomeCell *) [self.tableView dequeueReusableCellWithIdentifier:uniqueIdentifier];
if (!cell) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HomeCell" owner:nil options:nil];
for (id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[HomeCell class]])
{
cell = (HomeCell *)currentObject;
break;
}
}
}
if (tableView != self.searchDisplayController.searchResultsTableView) {
NSString *itemName = [object objectForKey:#"itemName"];
NSString *itemDescription = [object objectForKey:#"itemDescription"];
//cell.textLabel.text = last;
cell.cellTitleLabel.text = itemName;
cell.descriptionLabel.text = itemDescription;
cell.priceLabel.text = [object objectForKey:#"price"];
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = cell.imageFile;
thumbnailImageView.image = [UIImage imageNamed:#"Facebook #2x.png"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
}
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
PFObject *obj2 = [self.searchResults objectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:#"Items"];
PFObject *searchedItems = [query getObjectWithId:obj2.objectId];
NSString *itemName = [searchedItems objectForKey:#"itemName"];
NSString *itemDescription = [searchedItems objectForKey:#"itemDescription"];
cell.cellTitleLabel.text = itemName;
cell.descriptionLabel.text = itemDescription;
cell.priceLabel.text = [searchedItems objectForKey:#"itemName"];
PFFile *thumbnail = [searchedItems objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = cell.imageFile;
thumbnailImageView.image = [UIImage imageNamed:#"Facebook #2x.png"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
}
return cell;
Any help would be greatly appreciated,
cheers
In order to update the table view, you need to call the reloadData: method once you have added the new search results. Make sure that you call this method within the block that you provide to findObjectsInBackgroundWithBlock: because this block of code will be run on a separate thread. This causes the method to return instantly, and code after this method will then run before the block has actually executed. Your find objects code within filterResults: should look something like this:
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// This block is called from a background thread once the query has been executed
NSLog(#"%#", objects);
NSLog(#"%u", objects.count);
[self.searchResults addObjectsFromArray:objects];
// Refresh the table view on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
[self.searchDisplayController.searchResultsTableView reloadData];
});
}];
Differentiate from your search table view and your regular tableview when you create the cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
if (tableView = self.tableView) {
//Configure your cell normally
}
else {
//Configure your cells using
cell.someAttribute = self.searchResults[indexPath.row].someAttribute;
}