Compare and Match Array Values - ios

When the user searches for a category I need all the arrays that contain that same category to appear + the other categories that are in that respective array.
Once the user has chosen ["Apples", "Oranges", "Limes"] I want to compare which array (out of many) that I queried contains Apples, Oranges or Limes. This can be one array or this can be many arrays.
These are the arrays I'm adding the values to:
var categoryNeeded = [AnyObject]() //The user creates this one and adds values to it
var categoryArr = [AnyObject]() //The Parse arrays are added here:
I have a simple Parse query function.
var query : PFQuery = PFUser.query()!
query.whereKey("contacts", containsString: "\(categoryArr)")
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects as [PFObject]! {
for object in objects {
self.categoryArr.append(object["contacts"] as! AnyObject)
print(self.categoryArr)
}
}
}
The 2nd line is suspect:
query.whereKey("contacts", containsString: "\(categoryArr)")
When querying with that line, I get this error (without a crash):
2016-01-23 15:53:47.508 CC[28514:5733236] [Error]: $regex only works
on string fields (Code: 102, Version: 1.11.0)
Without the whereKey line, I get all the values and it prints them. I just can't figure out how to compare and check for matches between the two arrays which ultimately gives the matching arrays. Is there a Swift method that does that?

You should not use containsString but rather containedIn:
query.whereKey("contacts", containedIn: categoryArr)

Related

Adding integers in for loop and printing the total

I am looping through integer objects and want to add each integer to an integer variable, then when the for-loop is done, print the total. Is there an easy way to do this? Right now, I can retrieve the objects and print them individually, but the total prints as 0 every time.
Please see the code below. This is for an app written in Swift with Parse as the backend.
Anything helps, and thank you!
var itemsArray = [Int]()
let followingUserItemsQuery = PFUser.query()
followingUserItemsQuery?.whereKey("objectId", equalTo: (PFUser.currentUser()?.objectId!)!)
followingUserItemsQuery?.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error) in
if let objects = objects {
for object in objects {
let followingUsersArray = (object["following"] as! [String])
// Get number of listed items of following users with PFUser query for their total objects
for followingUser in followingUsersArray {
print(followingUser)
let query = PFUser.query()
query?.whereKey("objectId", equalTo: followingUser)
//Get each user's listedItems count then append to a higher-level integer variable
query?.getFirstObjectInBackgroundWithBlock({ (object, error) in
itemsArray.append(object!["listedItems"] as! Int)
})
}
}
}
let itemsSum = itemsArray.reduce(0, combine: +)
print(itemsSum)
self.followingUsersAddedItems.text = String("Your followers listed "+String(itemsSum)+" items")
Try this:
var count = 0
...
for followingUser in followingUsersArray {
count += object!["listedItems"] as! Int
}
Your code to reduce / combine the Int values is correct. The problem is that it runs before any of the nested asynchronous Parse queries complete and execute their callbacks. So at the time it runs, itemsArray is still empty. You will need to redesign your code so that itemsSum is calculated only after all the various nested Parse queries have all completed.

Access Parse Array Elements

I have an array column in Parse that is called homeAddress. Inside it is the following value for a single row:
["111111","222222"]
I wish to access this in swift. I created a local array called homeAddress of String type. How can I store the first element in the Parse column (i.e. 111111) in the first element holder in local array i.e. homeAddress[0]? And then I need to store the 222222 in the homeAddress[1].
So what you want is load this data from parse. You can just call a Parse Query get the results and work with them:
let query = PFQuery(className:"ClassName")
query.findObjectsInBackgroundWithBlock {
(results, error) -> Void in
if (error == nil) {
for object in results!{
let homeAddress = object["homeAddress"] as! NSArray
}
}else {
print(error?.userInfo)
}
}
One way would be to trim first and last character and just separate values by comma:
var test = "[\("111111"),\("222222")]"
var trimmedStringRange = Range<String.Index>(start: test.startIndex.successor(), end: test.endIndex.predecessor())
var homeAddress = test.substringWithRange(trimmedStringRange).componentsSeparatedByString(",")
If your local array is empty, you can add your values from the parse array like this (after getting the array from Parse):
localHomeAddress.append(homeAddress)
This will put all values from homeAddress array in localHomeAddress array.
If you use a splice, you can ensure you are adding the values from index 0:
localHomeAddress.insertContentsOf(homeAddress, at:0)

PFQuery where array of pointers contains a certain PFObject

Objects in my class Deal have an attribute relatedContacts which is an array of pointers to Contact objects. I'm running the following query to determine whether the current Contact object is the target of a pointer in any Deal, prior to deleting the Contact.
let relatedContactObjects:NSArray = [self.contactObject] as NSArray
let relatedContactQuery:PFQuery = PFQuery(className: "Deal")
relatedContactQuery.fromLocalDatastore()
relatedContactQuery.fromPinWithName("Deals")
relatedContactQuery.whereKey("user", equalTo: PFUser.currentUser()!)
relatedContactQuery.whereKey("relatedContacts", containsAllObjectsInArray: relatedContactObjects as [AnyObject])
However this returns Parse Error 102: "Value type not supported for $all queries."
The Parse documentation says that containsAllObjectsInArray takes an NSArray, but Xcode shows a warning that NSArray is not implicity convertible to [AnyObject].
Any ideas how I can make this query work?
Edit: I looked at the contents of relatedContacts and it seems that each instance contains an array of dictionaries, example: [{"__type":"Pointer","className":"Contact","objectId":"BoLym053hX"},{"__type":"Pointer","className":"Contact","objectId":"AgpnxAFUBn"},{"__type":"Pointer","className":"Contact","objectId":"ob20tThdfp"}]
As suggested, I've also looked at the containedIn query constraint, but that is used to identify objects that are contained in a given array. I am trying to identify arrays that contain a given object.
Parse.com overloads equalTo: by allowing it to mean either: (a) a singular property equals the operand, or (b) an array property contains the operand. So you're objective is easily stated as follows:
relatedContactQuery.fromPinWithName("Deals")
relatedContactQuery.whereKey("user", equalTo: PFUser.currentUser()!)
relatedContactQuery.whereKey("relatedContacts", equalTo:self.contactObject)
Prior to the accepted answer, I also tried using loops to go through the arrays and identify whether they contained the current object, then incremented a count.
var dealsPointingToContactCount:Int = 0
func countDealsRelatedToContact() {
let dealsWithRelatedContactQuery:PFQuery = PFQuery(className: "Deal")
dealsWithRelatedContactQuery.fromLocalDatastore()
dealsWithRelatedContactQuery.fromPinWithName("Deals")
dealsWithRelatedContactQuery.whereKey("user", equalTo:PFUser.currentUser()!)
dealsWithRelatedContactQuery.whereKeyExists("relatedContacts")
dealsWithRelatedContactQuery.findObjectsInBackgroundWithBlock{(objects, error) -> Void in
if (error == nil) {
var dealsWithPointersToContacts:NSArray = objects! as NSArray
for deal in dealsWithPointersToContacts {
var dealContactsArray:NSArray = deal["relatedContacts"] as! [PFObject]
for contact in dealContactsArray {
if contact as! PFObject == self.object {
self.dealsPointingToContactCount++
println("Deals pointing to current contact: \(self.dealsPointingToContactCount)")
}
}
}
}
}
}

Querying the User table with a users objectId queried from another table

I'm trying to query my User table with the Users objectId queried from another table.
Here's my code:
func queryFriendsTable() {
var queryFriends = PFQuery(className: "Activity")
queryFriends.whereKey("type", equalTo: "friend")
queryFriends.whereKey("fromUser", equalTo: PFUser.currentUser()!)
queryFriends.includeKey("toUser")
var queryUserTable = PFUser.query()
queryUserTable!.whereKey("objectId", matchesKey: "toUser", inQuery: queryFriends)
queryUserTable!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
self.friendNamesArray.addObject(object["username"]!)
println(self.friendNamesArray)
}
}
}
}
}
Nothing is being returned when I run this query. I think the problem has to do with the fact that the toUser objectId in the Activity table is a pointer and not a string. (The toUser value I try to use in the matchesKey spot is a pointer)
So how can I get the objectId as a string from a pointer object using the inQuery method?
Your suspicions are correct. Parse won't find pointers when looking through the User's class. Instead what you'll need to do is create a string variable and set it equal to the result of queryFriends. So what that means is you'll have to run that query first, get the pointer back, and access it's objectId field as a string in order to use it in your following query.

How to get a query retrieving two objects from Parse via Swift

I have a parse database as in the picture.
I need to retrieve with a query code, two objects, for example the last created dates of type 2 and 3.
I am trying the codes below, but dont know how to merge these two queries (query2 and query3)? Or might there be another way to retrieve these two objects as one table?
var query2 = PFQuery(className: "stories")
query2.whereKey("Type", equalTo: 2)
query2.addDescendingOrder("createdAt")
query2.getFirstObject()
var query3 = PFQuery(className: "stories")
query3.whereKey("Type", equalTo: 3)
query3.addDescendingOrder("createdAt")
query3.getFirstObject()
I don't think you could do exactly what you currently have with 1 query. You could combine them but only to get back an array of all 2 and 3 types and then split them out yourself.
If the issue is making 2 different network requests then you could create a cloud code function to run the 2 queries and return the results in a single response.
you can do this one query as well
var query2 = PFQuery(className: "stories")
query2.whereKey("Type", equalTo: 2)
query2.whereKey("Type", equalTo: 3)
query2.addDescendingOrder("createdAt")
You can change you approach too , you can send array to compare and sort results
query2.whereKey("Type", containedIn: #[2,3])
query2.addDescendingOrder("createdAt")
After this don't use getFirstObject ; get all array and get your desired results using predicate or any else , this will save one network call as well.
This is for getting 2 values from Array
NSArray *fullArray= All objects from the parse ;
NSMutableArray *selectedObjectsArray = [NSMutableArray array];
for(int i=0 ; i<fullArray.count ; i++){
if (selectedObjectsArray.count==1 && ![[[selectedObjectsArray objectAtIndex:0] objcetForKey:#"type"] isEqualToString:[[Full array objectAtIndex:i] objcetForKey:#"type"]]) {
[selectedObjectsArray addObject:[fullArray objectAtIndex]];
break ;
}else{
[selectedObjectsArray addObject:[fullArray objectAtIndex]];
}
}
In Swift (i m not too good in swift so double check swift code before using)
for object in fullArray {
if (selectedObjectsArray.count==1 && ![[selectedObjectsArray[0][#"type"] isEqualToString:fullArray[i][#"type"]) {
selectedObjectsArray[1]=[fullArray[i];
break ;
}else{
selectedObjectsArray[0]=[fullArray[i];
}
}

Resources