UI disappearing and Parse queries blocked at semaphore_wait_trap - ios

At a time in my app, the user have a timeline where are displayed posts from their friends, but randomly, the queries are stopped and not executed anymore,
more exactly, I had a problem before that: my app was frozen at psynch_mutexwait, I fixed it by using: dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ }); for queries that runs on background thread, but more precisely:
I have 2 queries that runs in loop every 3 and 4 seconds respectively, made by 2 respective shcheduled NSTimer
the first query loop for new posts (in this case the user do not have to refresh manually):
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PFQuery *query = [PFQuery queryWithClassName:#"Posts"];
[query whereKey:#"user" notEqualTo:[PFUser currentUser]];
[query whereKey:#"user" containedIn:self.allFriends];
[qFriendInfo findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
//Used to display results in UICollectionView
self.AllPosts = [[NSArray alloc] initWithArray:objects];
}
});
the second query is querying users's state, for example if a user is "online", "offline", or "disconnected"
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" notEqualTo:[PFUser currentUser].objectId];
[query whereKey:#"objectId" containedIn:self.allFriendsIds];
[qFriendInfo findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
//Used to display results in UICollectionView
self.allUsers = [[NSArray alloc] initWithArray:objects];
}
});
All works properly by using dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
but randomly, the queries are stopped (the app is not frozen either...) (I can see this by NSLog in the console) and when I pause, in the left window I can see the background thread on semaphore_wait_trap
does anyone have an idea for how to fix that issue ?

Related

findObjectsInBackgroundWithBlock in dispatch block doesn't called

I'm trying to call below parse retrieving method in another dispatch block but it never calls. I'm suspect calling a block in another block doesn't allowed but not sure. Does anybody have any idea about why findObjectsInBackgroundWithBlock isn't called?
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PFQuery *query = [PFQuery queryWithClassName:#"quotes"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *tempQuotes = [[NSMutableArray alloc] init];
for (PFObject *object in objects) {
[tempQuotes addObject:[object objectForKey:#"quote"]];
}
quotes = tempQuotes;
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate postRefreshing];
});
});
I changed my inner parse query as below (without any background block) and it worked. I should know that you can't call a method in background if you are already in a dispatch block.
PFQuery *query = [PFQuery queryWithClassName:#"quotes"];
NSArray* quotesArray = [query findObjects];

IOS Parse is my nested query a good solution for comparing an object with a pointer?

Currently, I am querying the database twice to achieve a list of all users nearby who are not already being followed by the current user. Here is my nested query:
// List of all users being followed by the current user
PFQuery *followingActivitiesQuery = [PFQuery queryWithClassName:kFTActivityClassKey];
[followingActivitiesQuery whereKey:kFTActivityTypeKey equalTo:kFTActivityTypeFollow];
[followingActivitiesQuery whereKey:kFTActivityFromUserKey equalTo:[PFUser currentUser]];
[followingActivitiesQuery setCachePolicy:kPFCachePolicyNetworkOnly];
[followingActivitiesQuery includeKey:kFTActivityToUserKey];
[followingActivitiesQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *followedUserIds = [[NSMutableArray alloc] init];
// Obtain an array of object ids for all users being followed
for (PFObject *object in objects) {
PFUser *followedUser = [object objectForKey:kFTActivityToUserKey];
[followedUserIds addObject:followedUser.objectId];
}
PFGeoPoint *geoPoint = [[PFUser currentUser] objectForKey:kFTUserLocationKey];
// List of all users within 50 miles that are not already being followed
PFQuery *followUsersByLocationQuery = [PFQuery queryWithClassName:kFTUserClassKey];
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey notEqualTo:[PFUser currentUser].objectId];
[followUsersByLocationQuery whereKey:kFTUserLocationKey nearGeoPoint:geoPoint withinMiles:50];
[followUsersByLocationQuery whereKeyExists:kFTUserLocationKey];
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey notContainedIn:followedUserIds];
[followUsersByLocationQuery setLimit:100];
[followUsersByLocationQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.objects = objects;
[self.tableView reloadData];
}
}];
}
}];
My question is, is this a viable solution? I feel guilty about having to query the server twice in order to achieve this, but I was not able to do it all in one query. I could not compare a parse pointer from the ActivityClass to the Users class, since the Users class is the class being pointed to, and because of this I couldn't think of a way to do it all in one query.
You're in luck - this can be done in a single query using the whereKey:doesNotMatchKey:inQuery: method of PFQuery.
Parse will treat this as a single, compound query against the database. Totally guilt-free :)
Try this instead:
// List of all users being followed by the current user
PFQuery *followingActivitiesQuery = [PFQuery queryWithClassName:kFTActivityClassKey];
[followingActivitiesQuery whereKey:kFTActivityTypeKey equalTo:kFTActivityTypeFollow];
[followingActivitiesQuery whereKey:kFTActivityFromUserKey equalTo:[PFUser currentUser]];
[followingActivitiesQuery setCachePolicy:kPFCachePolicyNetworkOnly];
[followingActivitiesQuery includeKey:kFTActivityToUserKey];
PFGeoPoint *geoPoint = [[PFUser currentUser] objectForKey:kFTUserLocationKey];
// List of all users within 50 miles that are not already being followed
PFQuery *followUsersByLocationQuery = [PFQuery queryWithClassName:kFTUserClassKey];
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey notEqualTo:[PFUser currentUser].objectId];
[followUsersByLocationQuery whereKey:kFTUserLocationKey nearGeoPoint:geoPoint withinMiles:50];
[followUsersByLocationQuery whereKeyExists:kFTUserLocationKey];
//The next line is your new compound query
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey doesNotMatchKey:#"objectId" inQuery:followingActivitiesQuery];
[followUsersByLocationQuery setLimit:100];
[followUsersByLocationQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.objects = objects;
[self.tableView reloadData];
}
}];

Queries on array values on Parse.com isn't working

This is basically killing my app and Parse isn't exactly being prompt with their responses.
Queries on pointer arrays aint working.
Try this in your app:
- (void)runTest{
// Run a build to store 20 rows.
for(int i=0;i<20;i++){
NSMutableArray *recipients = [NSMutableArray array];
[recipients addObject:[PFUser currentUser]];
PFObject *message = [PFObject objectWithClassName:#"Run"];
[message addObjectsFromArray:recipients forKey:#"recipients"];
[message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
}];
}
}
- (void)runTestQuery{
// Run a second build to query the 20 rows. Not all 20 are returned.
PFQuery *query = [PFQuery queryWithClassName:#"Run"];
[query whereKey:#"recipients" equalTo:[PFUser currentUser]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
NSLog(#"Objects count: %li",(long)objects.count);
}];
}

Perform action after findObjectsInBackgroundWithBlock completed in for loop

I have such construction in my code:
for (METMeetingEntity *e in self.meetingList) {
PFQuery *query = [PFUser query];
//some query constraints, depending on METMeetingEntity
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
// some query actions
NSArray *sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"date" ascending:YES]];
self.meetingList = [NSMutableArray arrayWithArray:[self.meetingList sortedArrayUsingDescriptors:sortDescriptors]];
self.meetingList = [self dateCleanup:self.meetingList];
}];
How can I perform action - reload my table view after all the findObjectsInBackground are completed
One possible solution would be to keep a count. When the number matches the original count, you know you are done.
NSUInteger count = self.meetingList.count;
for (METMeetingEntity *e in self.meetingList) {
PFQuery *query = [PFUser query];
//some query constraints, depending on METMeetingEntity
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// some query actions
NSArray *sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"date" ascending:YES]];
self.meetingList = [NSMutableArray arrayWithArray:[self.meetingList sortedArrayUsingDescriptors:sortDescriptors]];
self.meetingList = [self dateCleanup:self.meetingList];
count--;
if (count == 0) {
dispatch_async(dispatch_get_main_queue(), ^{
// reload table or whatever needs to be done
});
}
}];
}
I think you don't need calling dispatch_async. All the blocks in Parse run in the main thread. In Parse doc you can read:
Both findObjectsInBackgroundWithBlock: and
findObjectsInBackgroundWithTarget:selector: work similarly in that
they assure the network request is done without blocking, and run the
block/callback in the main thread.
This is an example of a query for a UICollectionView:
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(!error) {
listaFiguras = [objects mutableCopy];
[_collectionView reloadData];
} else {
NSLog(#"Something wrong. No Data.");
}
}];

Parse sdk crashes on calling query api

I just try to write some sample app using parse backend, i created app and test class, its worked fine for ios, for same calls if i make a PFquery call to retrive objects its crashing on mac.
PFQuery *query = [PFQuery queryWithClassName:#"stock"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (query.cachePolicy != kPFCachePolicyCacheOnly && error.code == kPFErrorCacheMiss) {
// No-op on cache miss - since the policy is not CacheOnly, this
// block will be called again upon receiving results from the network.
return;
}}];
You are setting cachePolicy wrong.
Use this:
PFQuery *query = [PFQuery queryWithClassName:#"stock"];
[query setCachePolicy:kPFCachePolicyNetworkOnly];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
}
}];

Resources