Adding integers in for loop and printing the total - ios

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.

Related

Compare and Match Array Values

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)

Two constraints on one key in a Parse Query

I'm using Parse and my app is written in Swift. I have a golf app that allows a user to friend other users. The users can log their golf scores and then see their golf scores and their friend's scores in a leaderboard style tableViewController.
The problem I'm having is that Parse doesn't support two constraints on the same key in a query. I have a function that queries the users and their scores and stores them in an array of tuples (leadeboardData). I'm trying to querying the current user's PFRelation as well as the current user (variable "friendsRelation" and constant "friendQuery"). The class I query is the "GolfScorecard", which is where the scores are stored on Parse. I then called the "whereKey" method on the "golfer" key, which is where my user is stored under on Parse. I call "whereKey matchesQuery" for my friendsRelation query and then "whereKey equalTo" to try and get my current user. I then "includeKey" "golfer" so I can get the user info along with the score info. Any suggestions on how to go about this? I'm trying to do it all in one query but when the "whereKey" method is called on the same key ("golfer") the last one overrides the first one, which makes it only possible to get the friend info or the current user info but not both. I'm stumped how to include both. Thanks in advance.
Here is my function I call to make the query:
func loadLeaderboardData() {
leaderboardData.removeAll()
friendsRelation = PFUser.currentUser()?.objectForKey("friendsRelation") as? PFRelation
friendsRelation = PFUser.currentUser()?.objectForKey("friendsRelation") as? PFRelation
let friendQuery = friendsRelation?.query()
let query = PFQuery(className: "GolfScorecard")
query.whereKey("golfer", matchesQuery: friendQuery!)
query.whereKey("golfer", equalTo: PFUser.currentUser()!)
query.includeKey("golfer")
query.orderByAscending("score")
query.findObjectsInBackgroundWithBlock { (scoreCards: [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object:PFObject in scoreCards! {
let golfer:PFObject = object["golfer"] as! PFObject
self.leaderboardData.append(object,golfer)
dispatch_async(dispatch_get_main_queue()) {
self.leaderboardTableView.reloadData()
}
}
} else {
print(error)
}
}
}
Thanks Paulw11 the orQueryWithSubQueries worked. The only issue it ended up presenting was my app was crashing with an error stating 'Key "username" has no data. Call fetchIfNeeded before getting its value.'...I don't think the Parse Query was coming back in time to load in the tableView that I was putting the data in. I ended up using the 'fetchIfNeededInBackgroundWithBlock' method inside of the cellForRowAtIndexPath call around the code where I was calling the 'username' data at. This allowed it to grab the data in the background if it didn't come back in time. This seemed to due the trick.
-Also I subclassed my queries, which is where the GolfScorecard & GolferProfile is coming from inside of my for-in loop.
-This is my new compound Query:
func loadLeaderboardData() {
leaderboardData.removeAll()
friendsRelation = PFUser.currentUser()?.objectForKey("friendsRelation") as? PFRelation
let friendQuery = friendsRelation?.query()
let friendScorecardQuery = PFQuery(className: "GolfScorecard")
friendScorecardQuery.whereKey("golfer", matchesQuery: friendQuery!)
let currentUserScorecardQuery = PFQuery(className: "GolfScorecard")
currentUserScorecardQuery.whereKey("golfer", equalTo: PFUser.currentUser()!)
let subQuery = PFQuery.orQueryWithSubqueries([friendScorecardQuery, currentUserScorecardQuery])
subQuery.orderByAscending("score")
subQuery.findObjectsInBackgroundWithBlock { (scoreCards: [PFObject]?, error: NSError?) -> Void in
if error == nil {
for object:PFObject in scoreCards! {
if let object = object as? GolfScorecard {
let golfer = object["golfer"] as! GolferProfile
self.leaderboardData.append(object,golfer)
dispatch_async(dispatch_get_main_queue()) {
self.leaderboardTableView.reloadData()
}
}
}
} else {
print(error)
}
}
}

Parse backend: key won't increment?

I'm trying to increment a number in my parse table under the column "votes". Here's my code:
func upVote() {
var reviewQuery: PFQuery = PFQuery(className: "reviews")
reviewQuery.whereKey("content", equalTo: reviewTextView.text)
reviewQuery.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects{
println(object)
let review:PFObject = object as! PFObject
review.incrementKey("votes", byAmount: 1)
}
}
}
}
When I print the object in the console I can see that it is the correct object that I'm looking for. It looks like this:
<reviews:ZqgSVL1Tsd:(null)> {
content = "njk\n";
reviewer = "<PFUser:6387CJtYI1>";
votes = 1;}
But when I look at my parse end, the number of votes has not changed. What am I doing wrong?
Save the object with
review.saveInBackground()
after incrementing the key.
After you modify an object, however small the modification, you must save it after. You are not saving your changes to the object review.
You have several options for saving, including save(), saveInBackground(), saveEventually(), and more. See the documentation for PFObject for more information:
https://www.parse.com/docs/ios/api/Classes/PFObject.html#//api/name/save
For example, you could save the object synchronously with
review.save() and you could save the object asynchronously with review.saveInBackground().

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)")
}
}
}
}
}
}

Trying to do two Parse PFQueries but getting error - in SWIFT

I am currently doing two PFQueries at once, one which is a PFUser.query and one which is a standard object query. These are both trying to execute roughly at the same time. I get no errors in the code until it runs it says:
'Cannot do a comparison query for type: Swift._NSSwiftArrayImpl'
I can only assume this is because I am trying to do two different queries at once?
Can somebody add some input into what it means a bit more and how maybe to overcome it?
the code I have used for both queries is:
var query = PFQuery(className: "Traits")
query.whereKey("name", equalTo: self.names)
var waveUsers = query.findObjects()
if waveUsers != nil {
self.profile.waves.removeAll(keepCapacity: true)
for waveUser in waveUsers{
self.profile.waves.append(waveUser["waves"] as Int)
}
}
and the PFUser Query:
var query = PFUser.query()
query.whereKey("location", nearGeoPoint:geopoint)
query.limit = 20
var users = query.findObjects()
if users != nil {
self.profile.names.removeAll(keepCapacity: true)
self.profile.images.removeAll(keepCapacity: true)
self.profile.genders.removeAll(keepCapacity: true)
self.profile.locations.removeAll(keepCapacity: true)
self.profile.status.removeAll(keepCapacity: true)
self.profile.rStatus.removeAll(keepCapacity: true)
self.profile.age.removeAll(keepCapacity: true)
for user in users {
{
self.profile.names.append(user["name"] as Int)
self.profile.images.append(user["image"] as NSData)
self.profile.genders.append(user["gender"] as NSString)
self.profile.locations.append(user["location"] as PFGeoPoint)
self.profile.rStatus.append(user["relationship"] as NSString)
self.profile.age.append(user["age"] as NSInteger)
self.profile.status.append(user["status"] as NSString)
self.appsTableView.reloadData()
user.save()
}
}
thanks in advance
If you want to test whether the "name" col can be found in your self.names array, then use containsAllObjectsInArray:
equalTo operates on single objects (it can test for a single object's presence in an array type column, but you're attempting the other way around).
EDIT - Lets say you have an array of strings, and you'd like to find objects whose string column an be found in the array...
// find people in the People class who were SNL cast members
var array = ["belushi", "akroyd", "radner"];
var queries = [];
// assume underscorejs
_.each(array, function(name) {
var query = new Parse.Query("People");
query.equalTo("lastName", name);
queries.push(query.find());
});
Parse.Query.or(queries).then(function() {
var snlCastMembers = _.toArray(arguments);
});

Resources