I've a small problem. I am working on an App using Parse backend. So my problem is:
i've retrieved all the objectIds of users in _User class like this:
var userIds = [String]()
var userQuery = PFUser.query()
userQuery?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.userIds.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
if user.objectId != PFUser.currentUser()?.objectId {
self.userIds.append(user.objectId!)
}
}
}
}
println(userIds)
})
Now i want to save all the userIds which are stored in the array "userIds" to a column in a class named "Something". so the code will be like:
var something:PFObject = PFObject(className: "Something")
something["users"] = // have problem here
something.saveInBackground()
if i put userIds here, it gives an error.. because userIds is an array but column "users" is String.. but also i want to save all the userIds seperately in the column "users" like it is saved in objectId column of _User class..
I'm new here and I can't comment in the reply where you asked for help. Anyway, what do you want now is save only new users, as you said:
I just want to save the users which are not there
Well, there are some suggestions:
You can retrieve your User class and check for new users manually in the app and then send the new ones to your Class.
You can create a new column in your User class like "saved" where contains a boolean indicating if you already saved this user to your custom class or not. Remember also, of always do
user["saved"] = false
while creating a new user and then simply do:
let search = PFQuery(className: "_User")
search.whereKey("saved", equalTo: false)
to get these non saved users.
I strongly recommend the second option.
Ok, the case that you describe should look something like this:
var userIds = [String]()
var userQuery = PFUser.query()
userQuery?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects as? [PFUser] {
var somethingObjects = [PFObject]()
self.userIds.removeAll(keepCapacity: true)
for user in users {
if user.objectId != PFUser.currentUser()?.objectId {
self.userIds.append(user.objectId!) // I don't know if this is necessary anymore for your usecase
var something:PFObject = PFObject(className: "Something")
something["users"] = user.objectId
somethingObjects.append(something)
}
}
PFObject.saveAllInBackground(somethingObjects)
}
})
In this case, you create a number of something objects that are saved, but you might want to rename the "users" column to "user", since you only save one objectId per row.
I haven't worked with parse in a while, so there might be a way to optimize the number of API calls you have to make.
Related
I created a query with subquery
var userInitiated = PFQuery(className: "friends")
userInitiated.whereKey("friender", equalTo: PFUser.currentUser()!.username!)
var friendInitiated = PFQuery(className: "friends")
friendInitiated.whereKey("friendee", equalTo: PFUser.currentUser()!.username!)
// find friends of user
let friendQuery = PFQuery.orQueryWithSubqueries([userInitiated, friendInitiated])
friendQuery.findObjectsInBackgroundWithBlock ({ (objects:[PFObject]?, error:NSError?) in
if error == nil {
// cleanup
self.friendArray.removeAll(keepCapacity: false)
// STEP 2 Hold Recieved Data
// find objects that you queried for
for object in objects! {
self.friendArray.append(object.valueForKey("-----") as! String)
}
}
})
In the for object in objects part - I want to append the usernames that I got from the query but I only want to add the ones that aren't the current users username, how would I do that?
A is current User, B is one of A's friends. So what the (friender, friendee) pair in your "friends" class?
Both (A,B), (B,A)
one of (A,B) and (B,A)
In first case, you can just query friender equalTo currentUser
In second case, your query seems ok.
I am creating a Sign Up Table on Swift using Parse to store data. Users can select maximum of 4 activities from the given list of activities.
I want the table to store all the 4 records of selected separately. But the code only makes one record!
Here is the code snippet-
//Creating a NSMutableSet to avoid multiple selection of same sport.
var tempSport = NSMutableSet()
//The vales in tempSport are : ["Activity1", "Activity2", "Activity3", "Activity4"]
#IBAction func getStartedButton(sender: AnyObject) {
if tempSport.count < 1
{
//Display Alert
}
else
{
var sendSport = Array(tempSport.allObjects)
print(sendSport)
for sport in sendSport
{
SportList["SportPlayer"] = user.username
SportList["SportPlaying"] = String(sport)
SportList.saveInBackground()
}
}
}
Image Link. Click here to see the expected output and output produced
Just save the object with an Array instead of 4 individual objects
let object = PFObject(className: "Your Class Name"
object["Sport Playing"] = [activity1, activity2, activity3, activity4]
object.saveInBackground()
Hope this helps.
Are you sure that you want to create a up to four sport objects for each user? That could end up becoming a lot of data in your database. I would recommend creating a a list of sports in the Parse database (soccer, football, tennis, etc) and create an array of users for each sport. For example, you would have Soccer under SportPlaying and an array of user objectIds under SportPlayer. Lets say you have a user with an objectId of H67c0uTUO1 that says they play Soccer, Basketball, and Lacrosse. You could send this data up to Parse by querying for the name of each sport that the user plays and adding the user's objectId to to the array using .addObject. Then, if you want a list of users who play that certain sport, you would query for using:
let sportQuery = PFQuery(className: "_User")
sportQuery.whereKey("objectId", containedIn: yourArrayFromSportPlayerForSpecificSport as! [anyObject])
let query = PFQuery.orQueryWithSubqueries([sportQuery])
query.findObjectsInBackgroundWithBlock { (results: [PFObject]?, error: NSError) -> Void in {
}
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)
}
}
}
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);
});
I have a query that gets latest posts by users. Each post has an "Owner" field that has the "ObjectId" of the account that created it. I do this because I want to also display the username of the person who created the post - which is found in the User table.
I looked at the Parse documentation for Queries and came up with this (modeled after one of their examples):
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt");
var innerQuery = PFQuery(className: "User")
innerQuery.whereKey("objectId", matchesQuery: query)
Then I run the findObjectsInBackgroundWithBlock. I don't think I'm getting the information from the User table to get the name of the person who posted the post.
I looked at the object that contains the information for the post but I don't see the information for the user in that object. What am I doing wrong?
Here are screenshots of the headers of my two tables:
POST:
USER:
Thanks!
I think the problem as that you refer to the user table in the query as "PFQuery(className: "User")". But if you use the built in user table, it's name is actually "_User". So use that, or even simplier, use:
var innerQuery = PFUser.query()
Try this
var class = PFQuery(className:"Post")
var finduser:PFQuery = PFUser.query()
finduser.whereKey("objectId", equalTo: class.objectForKey("owner").objectId)
finduser.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if (error == nil){
if let userObjects = objects {
let UserResult = (userObjects as NSArray).lastObject as? PFUser
if let user = UserResult {
println(user.username)
}
}
}
}