How can i perform a PFRelation query using parse in ios - ios

I have created a relation between two tables
LocationClass Table In this table i have a column with location images with the relation of another table ie., Assets
![This is location Class Image, If user selected a locationName, need to get the locationImages(viewRelation)][1]
Assets Table, It contains Images for each relation Now my query is how to get the data from relation database. Here if user select a location means i need to get a group of images for the relevant location ![This is my Assets Table, here need to retrieve the images based on the selected location from the locationClass Table][2]
Till now, I have done with this format
PFQuery *queryObj = [PFQuery queryWithClassName:#"LocationClass"];
sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
// Run the query
[queryObj whereKey:#"locationImages" equalTo:[PFObject objectWithoutDataWithClassName:#"Assets" objectId:#"aAPzhdO4w6"]];
[queryObj findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error)
{
[locationArray addObjectsFromArray:objects];
sharedDelegate.locationsArray = locationArray;
[locationDropDown reloadData];
}
}];
In my location array for a single object contain
<__NSArrayM 0xaee4eb0>(
<LocationClass:ZtOP9voUak:(null)> {
LocationId = WilliamsBurgId;
LocationName = WilliamsBurg;
locationImages = "<PFRelation: 0xaf53c30>(<00000000>.(null) -> Assets)";
}
)

Solution for to pass the data from PFRelation Object
// should pass the main table name
PFQuery *query = [PFQuery queryWithClassName:#"LocationClass"];
// should pass object id for the selected row
PFObject *getImageObject = [query getObjectWithId:#"need to pass object id from the maintable"];
locationImagesArray = [[NSMutableArray alloc]init];
// To acess the data from the relation object
PFRelation *relationObj = [getImageObject relationForKey:#"locationImages"];
PFQuery *query1 = [relationObj query];
[query1 findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
[locationImagesArray addObjectsFromArray:results];
for (int imgCount = 0; imgCount < [locationImagesArray count]; imgCount ++) {
PFFile *getImage1 = [[locationImagesArray valueForKey:#"Image"] objectAtIndex:imgCount];
[getImage1 getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error)
{
if (imageData!=nil) {
UIImage *image = [UIImage imageWithData:imageData];
activityImage.image = image;
NSLog(#"location image output");
NSLog(#"location image output : %#", activityImage.image);
}
}];
}

Related

How to run a loop of parse queries?

I am making an app that registers users and allows them to add friends etc. So I have a LoginViewController where I retrieve the array of user's friends' objectIds when the login is successful. This function is called.
- (void) getFriendList
{
NSString * objectID = [PFUser currentUser].objectId;
NSLog(#"%#", objectID);
PFQuery *query = [PFUser query];
[query getObjectInBackgroundWithId:objectID block:^(PFObject *username, NSError *error) {
sharedClass.sharedInstance->retrievedFriends = username[#"friendsIds"];
friendListLoaded = YES;
[self getFriendsUsernames];
}];
Here i get an array object that contains object ids of all the friends this user has. As you can see when getFriendList is completed, it calls another function called GetFriendsUsernames. This function is supposed to retrieve profile pictures and usernames of those friends so I can populate the Friend List view later.
-(void) getFriendsUsernames
{
NSMutableArray * objectIDs = [[NSMutableArray alloc] initWithArray: sharedClass.sharedInstance->retrievedFriends];
PFQuery *query = [PFUser query];
int friendsCount = [objectIDs count];
for(int i = 0; i<=friendsCount;i++)
{
[query getObjectInBackgroundWithId:objectIDs[i] block:^(PFObject *username, NSError *error) {
[sharedClass.sharedInstance->friendsUsernames addObject:username[#"username"]];
[sharedClass.sharedInstance->friendsProfilePictures addObject:username[#"ProfilePicture"]];
}];
NSLog(#"%#", sharedClass.sharedInstance->friendsUsernames );
}
}
But this seems to be unsuccessful because nothing is logged on the console where it should log username of retrieved friend whenever one query gets finished. Am I doing this the right way? My array count is right so loop runs to the number of friends a user has. It also prints the username of first object in objectIds array if i put the logging command in the loop.
Your NSLog runs immediately after your query objects are queued for execution. Therefore, even if the code is running correctly (and I suspect it might not be), you'll never get the correct results you're after logged to the console.
If you have your Parse classes designed in a certain way, you could collapse this into 1 query by using the include method on PFQuery. This assumes that you've created an array of Pointers on your User object, named "friends". If you actually store the objectId (i.e., the string value) of each friend, this code won't work.
I'm not using Swift yet, so here's how I'd write this query in Objective-C:
- (void)getFriendList {
PFUser *currentUser = [PFUser currentUser];
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" equalTo:currentUser.objectId];
[query includeKey:#"friends.username"];
[query includeKey:#"friends.ProfilePicture"];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *user, NSError *error) {
if (error != nil) {
// Process the error
} else }
// You've got your user and the data you wanted
}
}];
}
Found it. Not the prettiest way out there but well it does what i want. gets me arrays of usernames and profile pictures of every objectID contained in array of friends.
NSMutableArray * objectIDs = [[NSMutableArray alloc] initWithArray: sharedClass.sharedInstance->retrievedFriends];
PFQuery *query = [PFUser query];
PFFile * imageFile;
//UIImage *profilePictureData;
int friendsCount = [objectIDs count];
for(int i = 0; i<friendsCount;i++)
{
PFObject * username = [query getObjectWithId:objectIDs[i]];
[sharedClass.sharedInstance->friendsUsernames addObject:username[#"username"]];
[sharedClass.sharedInstance->friendsEmailAdresses addObject:username[#"email"]];
//NSLog(#"%#",username[#"ProfilePicture"]);
imageFile = [username objectForKey:#"ProfilePicture"];
NSData *imageData = [imageFile getData];
UIImage *imageFromData = [UIImage imageWithData:imageData];
[sharedClass.sharedInstance->friendsProfilePictures addObject:imageFromData];
NSLog(#"%#", sharedClass.sharedInstance->friendsUsernames );
}

Parse, getting pointer objects stored in an array along with primary object query

i have a "Station" object, it contains a column named "imagePointers", the array is populated as such:
[{"__type":"Pointer","className":"Image","objectId":"4Xtj32BOQy"},{"__type":"Pointer","className":"Image","objectId":"7DHCt7cx0O"}]
The pointers point at another object named Image, but they are stored as an array at the station object.
In iOS i query the station object as such:
PFGeoPoint *geoPoint = [PFGeoPoint geoPointWithLatitude:coordinate.latitude
longitude:coordinate.longitude];
[query whereKey:#"location" nearGeoPoint: geoPoint];
[query includeKey:#"imagePointers.Image"];
//[query orderByDescending:#"createdAt"];
return query;
When i receive the station object, the imagePointers field is empty? Completely empty
It seems like what you're trying to do is not supported by Parse.com. See this question.
Something like this might get you part of the way there. I'm using PFFiles to store images and then using the URL for the PFFile to load them in UIImageView with AFNetworking category
[query includeKey:#"imagePointers"];
[query findObjectsInBackgroundWithBlock:^(NSArray *stations, NSError *error) {
NSArray *imagePointers = stations[0][#"imagePointers"];
for (PFObject *images in imagePointers) {
[image fetchIfNeeded];
// add image to local array or something
}
}];
// it's possible you might need to do something like this...
PFObject *station = stations[0];
[station fetchInBackgroundWithBlock:^(PFObject object, NSError error) {
NSArray *imagePointers = stations[#"imagePointers"];
for (PFObject *images in imagePointers) {
[image fetchIfNeeded];
}

Get Array With Array but it's goes array in array

I have data on database like this.
["{37.331622, -122.030337}","{37.331593, -122.03051}","{37.331554, -122.030681}","{37.331383, -122.030757}","{37.33108, -122.030772}","{37.330798, -122.030729}","{37.330636, -122.030636}"]
Then i try to query data from database by following code.
- (void)updateLocations {
CGFloat kilometers = self.radius/1000.0f;
//PFUser *user = [PFUser currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"Session"];
[query whereKey:#"objectId" equalTo:#"t2udAri048"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"objects %#",objects);
NSLog(#"path %#",[objects valueForKey:#"Path"]);
NSArray *pointsArray = [objects valueForKey:#"Path"];;
NSInteger pointsCount = pointsArray.count;
CLLocationCoordinate2D pointsToUse[pointsCount];
for(int i = 0; i < pointsCount; i++) {
CGPoint p = CGPointFromString(pointsArray[i]);
pointsToUse[i] = CLLocationCoordinate2DMake(p.x,p.y);
}
MKPolyline *myPolyline = [MKPolyline polylineWithCoordinates:pointsToUse count:pointsCount];
[self.mapView addOverlay:myPolyline];
//NSLog(#"Drawed %#",pointsArray);
}
}];
}
I get the value of [objects valueForKey:#"Path"]
(
(
"{37.331622, -122.030337}",
"{37.331593, -122.03051}",
"{37.331554, -122.030681}",
"{37.331383, -122.030757}",
"{37.33108, -122.030772}",
"{37.330798, -122.030729}",
"{37.330636, -122.030636}"
) )
But i want it to
(
"{37.331622, -122.030337}",
"{37.331593, -122.03051}",
"{37.331554, -122.030681}",
"{37.331383, -122.030757}",
"{37.33108, -122.030772}",
"{37.330798, -122.030729}",
"{37.330636, -122.030636}"
)
What should i do?
It looks as if objects is an array of one element, which is an object with the "Path"
property. In that case you should replace
NSArray *pointsArray = [objects valueForKey:#"Path"];
by
NSArray *pointsArray = [objects[0] valueForKey:#"Path"];
In your example you have the objectId. If that is the case, you use getObjectWithId. This will return only the object you want.
PFQuery *query = [PFQuery queryWithClassName:#"Session"];
[query getObjectWithId:#"hr46gjh45"];
Your example returns an array of objects; in this case the array has only one object (but it is still an array). In that case you must first retrieve the object from the array.

Query Object Titles to Labels

I have a Parse query that runs to gather the 10 closest Arcades in your area, and I am trying to have them display those object titles in 10 separate labels. I have the following code which gathers the 10 closest and logs them, and I am trying to start by displaying the objectId in the labels but cannot figure out how to display them all and not just 1. Any suggestions?
PFQuery *query = [PFQuery queryWithClassName:#"Arcade"];
CLLocation *currentLocation = locationManager.location;
PFGeoPoint *userLocation =
[PFGeoPoint geoPointWithLatitude:currentLocation.coordinate.latitude
longitude:currentLocation.coordinate.longitude];
query.limit = 10;
[query whereKey:kPAWParseLocationKey nearGeoPoint:userLocation withinMiles:kPAWWallPostMaximumSearchDistance];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d scores.", objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
NSString *EventTitle = object.objectId;
EventTitle1.text = EventTitle;
for (UIImageView *imageView in self.imageViews) {
__block UIImage *MyPicture = [[UIImage alloc]init];
PFFile *imageFile = [object objectForKey:#"test"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error){
if (!error) {
MyPicture = [UIImage imageWithData:data];
imageView.image = MyPicture;
}
}];
}
for (UILabel *EventLabel in self.EventTitles){
EventLabel.text = object.objectId;
}
}
UPDATE: I have created two collection outlets, however when they display they only display the final object queried, not all 10 of them? Am I doing something wrong?
Your problem is EventTitle1.text = EventTitle;, because you explicitly reference the label. What you should be doing is updating the labels in sequence. This could be done by having the labels in an array (perhaps an IBOutletCollection) and using the iteration index. Or you could tag all of the labels and then look them up (again, using the iteration index).
But, your intended solution isn't simple and doesn't scale. It would be better to use a table view (Parse SDK even gives you an easy way to populate a table view from a query).

Remove an item from a column type of array in Parse (iOS SDK)

I have table name "Events". In that table I have a column of type array of string. I'm struggling with how I can delete only one element from that column. Consider the image below, I want to delete all the occurrences of "iYYeR2a2rU" from the "usersIncluded" column, without deleting the rows.
I've used the removeObject:(id) forKey:(NSString *) and it didn't work.
This is how I'm trying to achieve it:
PFQuery *query = [PFQuery queryWithClassName:#"Events"];
NSArray *eventObjects = [query findObjects];
[query whereKey:#"usersIncluded" equalTo:[self.uniqeFriendList objectAtIndex:indexPath.row]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error){
for (int i = 0; i<objects.count; i++) {
PFObject *event = [eventObjects objectAtIndex:i];
[event removeObject:[self.uniqeFriendList objectAtIndex:indexPath.row] forKey:#"usersIncluded"];
}
}];
}
The self.uniqeFriendList is a mutable array containing the ids that I want to delete from the 'usersIncluded' column.
Thanks in Advance
I think you're using the right method (removeObject:forKey: should do exactly what you want) but I think you're working with objects from the wrong array. You're performing your query twice, and within the findObjectsInBackgroundWithBlock: you're working with the array from the first time you called it... Try this:
PFQuery *query = [PFQuery queryWithClassName:#"Events"];
[query whereKey:#"usersIncluded" equalTo:[self.uniqeFriendList objectAtIndex:indexPath.row]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error){
for (int i = 0; i <objects.count; i++) {
PFObject *event = [objects objectAtIndex:i]; // note using 'objects', not 'eventObjects'
[event removeObject:[self.uniqeFriendList objectAtIndex:indexPath.row] forKey:#"usersIncluded"];
}
[PFObject saveAll:objects];
}];
}

Resources