PFUser not unwrapped - swift - ios

I'm beginning to learn swift with parse and i've run into this error:
"Value of optional type 'PFUser?' not unwrapped; did you mean to use '!' or '?'
I can't seem to get it to work...
PFFacebookUtils.logInWithPermissions(["public_profile",
"user_about_me", "user_birthday"], block: {
user, error in
if user == nil {
println("the user canceled fb login")
//add uialert
return
}
//new user
else if user.isNew {
println("user singed up through FB")
//get information from fb then save to parse
FBRequestConnection.startWithGraphPath("/me?fields=picture,first_name,birthday,gender", completionHandler: {
connection, result, error in
//print results
println(result)
//result dictionary about user
var r = result as NSDictionary
//prnt dictionary
println(NSDictionary)
//match parse column with what fb sends
user["firstName"] = r["first_name"]
user["gender"] = r["gender"]
//r = result, then key into using picture. Then key into url using the data
let pictureURL = ((r["picture"] as NSDictionary)["data"] as NSDictionary) ["url"] as String

Instead of using if user == nil {... you should really use
if let user = user {
// Login succeeded...
}
else {
// Login failed
}
The variable user will then be unwrapped inside the if let and you can continue using user the same way you are.

Here is explanation: What is an "unwrapped value" in Swift?
PFFacebookUtils.logInWithPermissions(["public_profile",
"user_about_me", "user_birthday"], block: {
user, error in
if user == nil {
println("the user canceled fb login")
//add uialert
return
}
//new user
else if user!.isNew {
println("user singed up through FB")
//get information from fb then save to parse
FBRequestConnection.startWithGraphPath("/me?fields=picture,first_name,birthday,gender", completionHandler: {
connection, result, error in
//print results
println(result)
//result dictionary about user
var r = result as NSDictionary
//prnt dictionary
println(NSDictionary)
//match parse column with what fb sends
user["firstName"] = r["first_name"]
user["gender"] = r["gender"]
//r = result, then key into using picture. Then key into url using the data
let pictureURL = ((r["picture"] as NSDictionary)["data"] as NSDictionary) ["url"] as String

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

Swift parse check user entered input and refresh value

I am trying to check if user entered data matches object data in a class. Comparing works, but refreshing does not.
This is the code.
let query = PFQuery(className: "registeredCodes")
query.whereKey("code", equalTo: userCodeEnter.text!)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if error != nil || object == nil {
print("The getFirstObject request failed.")
} else {
// The find succeeded.
print("Successfully retrieved the object.")
let totalPoints = PFUser.currentUser()?["points"] as? Int
self.userPointsLabel.text = "Punkte: " + "\(totalPoints)"
}
}
After
let totalPoints = PFUser.currentUser()?["points"] as? Int
self.userPointsLabel.text = "Punkte: " + "\(totalPoints)"
It just puts an "optional" in front of the original number, but not the new one. It looks something like optional(5)
Your code is querying (pulling an object from the server, with some check) for the registeredCodes class. Then, when that's done, your code is using the PFUser.currentUser to do something. This is a different class. The query will not result in an update to the PFUser.currentUser.
If PFUser.currentUser is expected to have changed then you need to call refreshInBackgroundWithBlock: on it to get those updates so you can use them (they will be ready when the completion block is called.

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 + Facebook Questions

I am trying to implement Parse + Facebook
Here is what I would like to do:
User Log In with Facebook
Login Authorized
A new User created from Facebook properties (gender, age, name, etc)
Below is my code which logs in to Facebook using PFFacebookUtils. The code successfully created a User on my Parse, but I don't have those details of the User from Facebook which I want to use.
I would like to get the user's name, gender, hometown, etc on Facebook.
How do I achieve that??
var permissionArray = ["public_profile","user_friends","email","user_birthday", "user_work_history", "user_education_history", "user_hometown", "user_location", "user_likes"]; on Facebook
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissionArray) { (user: PFUser?, error: NSError?) -> Void in
if user != nil {
if user!.isNew {
println("New User");
}
else {
println("Old User");
}
println(user?.username);
}
else {
println("Login Cancel")
}
}
You need to request the users "me" data, and then you can use that to populate your user object. So, in your if user!.isNew { you'll need to do something along the lines of...
let fbDetailsRequest = FBRequest.requestForMe()
fbDetailsRequest.startWithCompletionHandler { connection, result, error in
if error != nil {
// Handle the error
}
if let graph = result as? FBGraphObject {
// Now you can fill out the data on your user object
user!.setObject(graph.objectForKey("email")!, forKey: "email")
user!.setObject(graph.objectForKey("gender")!, forKey: "gender")
// Don't forget to save afterwards...
user!.saveInBackgroundWithBlock(nil)
}
}
To see the fields you can grab, check out https://developers.facebook.com/docs/graph-api/reference/user If you need anything other than "core" items, you might have to have extra permissions.

Assigning PFUser with A PFObject Swift

How can I add a PFUser to a PFObject, here is my code now:
var gameScore = PFObject(className: "SiteLog-\(jobName.text)")
gameScore["TypeOfWorks"] = "\(typeOfWorks.text)"
gameScore["DateAndTime"] = "\(formattedDate)"
gameScore.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
println("sucessfully sent to parse!")
} else {
// There was a problem, check error.description
println("Error Sending to Parse = \(error)")
}
So how would I be able to assign a user to it, the user is already logged in so how can I assign this PFObject to the current user logged in!
I am using iOS Swift - Xcode 6.3.1
Thanks,
George Barlow
In Objective-C you can reference the logged in user by calling [PFUser currentUser], which should translate to Swift as PFUser.currentUser(). Say you have a column for gameScore called user, you can add this line of code before saving gameScore:
if let user = PFUser.currentUser(), username = user.username {
user["column-name-in-parse-data"] = username
}

Resources