Parse Class Run Through For Loop - ios

My app uses Parse.com for most of its services. The main screen has a PFTableViewController, showing all the objects of a certain class. I would like to add all of these as NSUserActivity, so I know I need to run it through a for loop, but for the life of me, can't think of how to run the class through the loop to add each item from the class into a NSUserActivity.
What I have so far before setting up the table.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// The className to query on
self.parseClassName = #"Prayers";
// 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 = 20;
}
return self;
}
- (PFQuery *)queryForTable {
NSLog(#"QUERY");
PFQuery *query = [PFQuery queryWithClassName:#"Prayers"];
// 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:#"createdAt"];
return query;
}

There seems to be no real API for this... Please refer to this link for a possible workaround:
https://parse.com/questions/all-keys-or-method-or-query-to-determine-common-class-structure-of-all-objects-in-a-class-collection

Related

iOS Parse.com saving object with a pointer column gives "user not allowed" error

I'm trying to update an existing row in my Parse.com class from an iOS app. Upon doing so, I'm getting this error back from Parse:
This user is not allowed to perform the update operation on City. You can change this setting in the Data Browser. (Code: 119, Version: 1.9.1)
I have two Parse.com classes: City and Bar. The City class is read-only (it's a list of cities that won't change) and the Bar class is the class that users interact with (like adding comments, ratings, menu items, etc). Bar has a Pointer column on City and the permissions on Bar are all on for the public user.
Here's a snippet of code:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Bar"];
self.bar = [query getObjectWithId:self.barId];
self.bar.name = #"Foo";
[self.bar saveInBackground];
}
Some notes about the snippet: I'm passing in the bar's ID from the previous view controller via segue. I also know this is running the Parse query on the main thread and it's going to block...I'm simply prototyping right now and this is meaningless code.
Upon running that snippet, I get the error listed above. As you can see in the code, I'm not changing the city value nor am I even including it in the query results. I don't understand why I would be getting this error. Any input would be greatly appreciated!
Try this code and see if the 2 NSLog messages appear in the order you expect:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Bar"];
//self.bar = [query getObjectWithId:self.barId];
[query getObjectInBackgroundWithId:self.barId block:^(PFObject *result, NSError *error) {
NSLog(#"query has finished.");
self.bar = result[0];
}];
self.bar.name = #"Foo";
NSLog(#"Now going to saveInBackground.");
[self.bar saveInBackground];
}
And then try this, I think it may work, though I do not know all the details of your project:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Bar"];
//self.bar = [query getObjectWithId:self.barId];
[query getObjectInBackgroundWithId:self.barId block:^(PFObject *result, NSError *error) {
self.bar = result[0]; // or result; ??
self.bar.name = #"Foo";
[self.bar saveInBackground];
}];
}

How to call queryForTable to reload data from Parse cloud in PFQueryTableViewController?

I have a PFQueryTableViewController table, which is getting info from parse database. When user select a row it goes to another VC. In that VC user delete some data in Parse table. This Parse table is the same table I have loaded my PFQueryTableViewController. Therefore, I do not need these deleted data to be shown.
When user press back button, this method in PFQueryTableViewController get called:
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
[super objectsWillLoad];
}
I have checked line by line. It is reloading data but it is not calling:
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:#"MyClass"];
[query whereKey:#"user" equalTo:[PFUser currentUser]];
[query orderByDescending:#"createdAt"];
return query;
}
I deleted some data in the VC and dose not exist on the cloud. But when I press back button it exist. However, when I refresh the table, deleted data will be vanished!
I read documentation documentation but I can't find how I can call queryForTable method to connect to cloud and read data again.
You have to call this
[self loadObjects];
instead of
[self.tableView reloadData];

iOS: Proper way of initializing an object?

Modeled after Parse's PFQuery class, I'm building my own EMQuery class, for my own project (not a subclass of PFQuery). My question is, if I want to perform a similar call to a class method in the manner that Parse does it (PFQuery *query = [PFQuery queryWith...]) would this be the correct approach?
+ (instancetype)queryWithType:(EMObjectType)objectType {
EMQuery *query = [[self alloc] init];
return [query initWithQueryType:objectType];
}
- (id)initWithQueryType:(EMObjectType)objectType {
self = [super init];
if (self) {
}
return self;
}
No - as you are calling init of the superclass twice.
Your initWithQueryType should replace the call to init
+ (instancetype)queryWithType:(EMObjectType)objectType {
EMQuery *query = [self alloc];
return [query initWithQueryType:objectType];
}
The exception is if the init in your class does something. In that case the two inits init and initWithQueryType: should be set up that one calls the other and the one called is the only one that calls super init This one is the designated initialiser
The main explanation of all initialization is the section on Object Initialization Apple document
Don't call two init methods; call one, once. Like this:
+ (instancetype)queryWithType:(EMObjectType)objectType {
EMQuery *query = [[self alloc] initWithQueryType:objectType];
return query;
}

Ignore fetching if PFQuery is already running

how can I ignore new fetching if one is already running. Here is one example of my code:
So if i call [self getParticipants] how to make sure to ignore if already running. The only solution I've got is to create BOOL property "inMiddleOfFetching" but I dont want to create anther BOOL property just for this. Is there a better solution?
- (void)getParticipants {
PFQuery *participantsQuery = [self.participantsRelation query];
[participantsQuery includeKey:#"client"];
[participantsQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (objects)
self.participants = objects;
}];
}
This is not simpler but it is better, you can use bolts to create a single task for the query, this way if it is called multiple times it will only run once but all calls will return the value at the same time.
Something like this:
#property BFTask* task;
- (BFTask *)getParticipants {
if (!_task) {
PFQuery *participantsQuery = [self.participantsRelation query];
[participantsQuery includeKey:#"client"];
_task = [participantsQuery findObjectsInBackground];
}
return _task;
}
Then to get the result:
[[self getParticipants] continueWithBlock:^id(BFTask *task) {
if(!task.error){
self.participants = task.result;
}
_task = nil; //if you want to run the query again in the future
return nil;
}];

Parse PFQueryTableView loading User relation

Is it possible to use a PFQueryTableView with a User relation? For example I can easily list user relations (favorited items in this case) in a regular Tableview like so:
PFRelation *relation = [self.currentUser relationForKey:#"favorites"];
[[relation query] findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
// There was an error
} else {
// NSLog(#"%#", objects);
salesArray = nil;
salesArray = [[NSMutableArray alloc]initWithArray:objects];
[self.tableView reloadData];
}
}];
But PFQueryTableView requires you to put in a parseClassName. So would I put in the Users class here then overwrite objectsLoad method or something to obtain a specific logged in users favorites?
Not sure if this was the best solution but I created a Dummy class to avoid PFQueryTableView from automatically downloading data. I basically created an empty Class on Parse named Dummy. Then I just set my objects into self.objects and then [self loadObjects]; to refresh the tableview.

Resources