Unable to get currentUser PFUser object from Parse.com - ios

As you can see in the screenshot below, I have three users with usernames user1, user2 and user3 in the User table. I am trying to use the code below to get (so that I can update later) the User object with username = "user1". I dont get anything, I just get error.
When the function below is run, this is printed:
saveUserSalaryInfo() - found NOOO-NIL user matching pfquery criteria
This shows that it is always getting the error. Why? What am I doing wrong?
Code:
func saveUserSalaryInfo() {
if PFUser.currentUser() != nil {
var query = PFQuery(className:"User")
query.whereKey("username", equalTo: "user1")
query.findObjectsInBackgroundWithBlock {
(users: [AnyObject]?, error: NSError?) -> Void in
if error != nil {
NSLog("saveUserSalaryInfo() - found some user matching pfquery criteria")
}
else {
NSLog("saveUserSalaryInfo() - found NOOO-NIL user matching pfquery criteria")
}
}
} else {
NSLog("found error - current User is not logged in")
}
}

You are doing the test the other way around, if the error is nil that means no error happened
if error == nil {
NSLog("No error")
} else {
NSLog("Error")
}
Or to check if there is data use:
if users != nil {
NSLog("Find Users")
} else {
NSLog("Didn't find users")
}

Related

Fetching CloudKit User Record using UserRecordID

The question is to fetch data from User Records when UserRecordID is fetched.
Method to get User ID:
post.creatorUserRecordID?.recordName
My Users Record Type contains columns like username, so, I need to parse them for a concrete user. Is it possible somehow?
If I understood your question and you already have a CKRecordID. All you got to do then is to fetchRecordWithID using this CKRecordID you got.
let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
publicDatabase.fetchRecordWithID(recordId, completionHandler: { (fetchRecord: CKRecord?, fetchError: NSError?) in
if let error = fetchError
{
// error getting user record, try again
print("-> cloudKitFetchUserRecord - error fetching user record - Error \(error)")
}
else
{
if let record = fetchRecord
{
if record.recordType == CKRecordTypeUserRecord
{
// valid record
print("-> cloudKitFetchUserRecord - fetching user record - valid record found - \(record.recordID.recordName))")
// unwrap your values - on your case username
if let object = record.objectForKey("username") as? Bool
{
// do something with object
}
}
else
{
// not valid record
print("-> cloudKitFetchUserRecord - fetching user record - The record that came back is not a CKRecordTypeUserRecord")
}
}
else
{
// record nil
print("-> cloudKitFetchUserRecord - fetching user record - fetch record returned nil")
}
}
})
It is simpler now using async/await in Swift 5
func getUserID() async {
let container = CKContainer(identifier: "iCloud.com.XXX.XXXX")
// CKContainer.defaultContainer().publicCloudDatabase // or default public container
do {
let userRecordID = try await container.userRecordID()
print("recordName: \(userRecordID.recordName)")
}
catch {
print("Error: \(error)")
}

How to create pointer to Parse PFUser from facebook ID

I'm doing a Facebook graph call to get friends of the user that are using my app. I get the facebook ID of the user's friends back from the graph call. Below is what I'm attempting to obtain from Parse with that ID, but's it's not getting all the users back, I believe since its an async call. How can I save an array of pointers of the user's fb friends that are using the app? Thanks in advance!!
graphConnection.addRequest(requestFriends, completionHandler: { (connection: FBSDKGraphRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if result.objectForKey("friends") != nil {
// parsing dictionary to get results
let firstDict = result.objectForKey("friends")
let dataArray = firstDict!.objectForKey("data")
let myFriendsUsingTheAppCount = dataArray!.count
print("\(myFriendsUsingTheAppCount)")
let friendsArray:NSMutableArray = []
for var i = 0; i < dataArray!.count; i++ {
let friend = dataArray![i]
let friendFbObjectID = friend.objectForKey("id")!
let query = PFUser.query()
query!.whereKey("facebookID", equalTo: friendFbObjectID)
query!.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
// this is where I was going to save this specific user as a pointer
} else {
// some error
}
})
// this is saving just the friend's name/fb id to an array, but I want an array of pointers to the PFUser
friendsArray.addObject(friend)
}
} else {
// fb friends is nil
print("FB friends came back nil")
}
})
This could be simplified into a single query by using whereKey:containedIn:
let facebookIDs = dataArray.map { $0.objectForKey("id")! }
let query = PFUser.query()!
query.whereKey("facebookID", containedIn: facebookIDs)
The query will now contain all users whose facebook id is in the array passed to the query.
(swift syntax may be incorrect did not double check)

Parse orQueryWithSubqueries not working correctly (swift)

I'm working on implementing messaging functionality into my swift app, which runs on Parse, and querying for Conversation objects using the orQueryWithSubqueries method isn't working out like it should. Here is how I set up my query:
var user1 = PFQuery.getUserObjectWithId("someUserObjectID")
var user2 = PFQuery.getUserObjectWithId("otherUserObjectID")
var query1 = PFQuery(className: "Conversation")
query1.whereKey("user1", equalTo: user1!)
query1.whereKey("user2", equalTo: user2!)
var query2 = PFQuery(className: "Conversation")
query2.whereKey("user1", equalTo: user2!)
query1.whereKey("user2", equalTo: user1!)
var query = PFQuery.orQueryWithSubqueries([query1, query2])
query.includeKey("user1")
query.includeKey("user2")
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if (error == nil) {
println("Found conversation object!")
} else {
var errorCode = error!.code
if (errorCode == 101) {
println("Did not find conversation object!")
} else {
println("Unknown error occurred.")
}
}
}
Essentially, in my scheme a Conversation object is a PFObject with two relevant fields: user1 and user2... which simply defines the two users that the conversation is between. The reason that I need this query to work is that when a user wants to start a new Conversation with a friend... I first check if that Conversation exists, and this query is how I do that. Because I don't know who started the Conversation, I need to check for both users in both user fields (my app automatically fills the user1 field with whoever started the conversation).
Anyway, here's where the weird behavior is happening. I have a conversation object in the cloud where:
user1 = someUser
user2 = otherUser
If I run my query the way that it is typed above... the Conversation object is not found by the orQueryWithSubqueries (even though query1 should find the Conversation object!). However, if I remove query2 from the orQueryWithSubqueries, or even just comment out either whereKey constraint in query2... the Conversation object is found. This is weird because query2 shouldn't even have anything to do with finding the Conversation object! Because query1 is the one that matches the object, and orQueryWithSubqueries are supposed to return object that match either query. Can any one shed any light on what I'm doing wrong?
In case anyone else encounters this issue, I never did find a way to get the orQueryWithSubqueries to work properly (may be a bug in the Parse iOS SDK), but this was my workaround:
var query = PFQuery(className: "Conversation")
query.whereKey("user1", containedIn: [user1, user2])
query.whereKey("user2", containedIn: [user1, user2])
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if (error == nil) {
} else {
var errorCode = error!.code
if (errorCode == 101) {
} else {
// Handle error here.
}
}
}

How to prevent duplicate entry on parse?

I' trying to save song info to parse, but if the song already exist in parse I want my code just do nothing.
I've tried this code below:
var Music = PFObject(className:"Musics")
var query = PFQuery(className:"Musics")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
var songTitle = object.objectForKey("songTitle") as? String
if songTitle != title {
Music["createdBy"] = PFUser.currentUser()
Music["songTitle"] = title
Music["albumCover"] = imageFile
Music["songArtist"] = artist
Music.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
println("succeed")
} else {
// There was a problem, check error.description
println("error jeh")
}
}
}else{
println("song already exist")
}
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
the code above give below result on log:
Successfully retrieved 4 scores.
song already exist
Successfully retrieved 4 scores.
song already exist
Successfully retrieved 4 scores.
song already exist
Successfully retrieved 4 scores.
song already exist
succeed
succeed
succeed
succeed
succeed
succeed
succeed
succeed
succeed
succeed
succeed
succeed
Why my for loop , looping more than the Objects.count? and how can I prevent dupiclate entry on parse?
give me any advice, doesn't matter in obj c or swift
I suggest to implement a simple beforeSave trigger, on Parse Cloud code, in order to check if the new entry song already exist (basically you're going to make one or more field uniques. For example:
Parse.Cloud.beforeSave("Musics", function(request, response) {
var newEntrySong = request.object;
var querySongs = new Parse.Query("Musics");
querySongs.equalTo("title", newEntrySong.get("title"));
querySongs.equalTo("description", newEntrySong.get("description"));
// this could be a sort of signature for your song, to make more unique (skipping spaces and new lines for example)
querySongs.equalTo("md5Title", newEntrySong.get("md5Title"));
querySongs.first({
success: function(temp) {
response.error({errorCode:123,errorMsg:"Song already exist!"});
},
error: function(error) {
response.success();
}
});
});
Hope it helps.

How to preset Parse fields?

https://www.flickr.com/photos/dom497/16118311866/
Based off the picture linked above, here's the scenario: A user signs-up in my app and their data is added to Parse. How can I get ElginSupAccess to be preset to false?
I've tried using the following to update the field but apparently I cannot update an undefined field. (using Swift)
var query = PFQuery(className:"_User")
query.getObjectInBackgroundWithId(nameID) {
(update: PFObject!, error: NSError!) -> Void in
if error == nil {
update["elginSupAccess"] = false
update.saveEventually()
Dom,
In Parse the correct syntax of querying the user class is below, you don't query it by class name:
PFQuery *query = [PFUser query];
or for swift
var query = PFUser.query()
query.getObjectInBackgroundWithId("xWMyZEGZ") {
(update: PFObject!, error: NSError!) -> Void in
if error != nil {
NSLog("%#", error)
} else {
update["ElginSupAccess"] = false
}

Resources