Add column to PFUser AFTER signup? Parse, Swift - ios

I would like my user to add/edit details about their profile after they register with my app.
#IBAction func doneEditting(sender: AnyObject) {
self.completeEdit()
}
func completeEdit() {
var user = PFUser()
user["location"] = locationTextField.text
user.saveInBackgroundWithBlock {
(succeeded: Bool, error: NSError?) -> Void in
if let error = error {
let errorString = error.userInfo?["error"] as? NSString
println("failed")
} else {
self.performSegueWithIdentifier("Editted", sender: nil)
}
}
}
the breakpoint stops right at user.saveInBackgroundWithBlock. No of the docs show how to append new columns after the signup.
Thanks!

You are mentioning that the user should be able to edit their profile after they have registered. When registering a user with Parse using signUpInBackgroundWithBlock, then the Parse SDK will automatically create a PFUser for you.
In your provided code you are creating and saving a completely new PFUser instead of getting the one which is currently logged in. If you are not using the PFUser which is logged in, then you will get the following error at user.saveInBackgroundWithBlock (which you are also mentioning in your post):
User cannot be saved unless they are already signed up. Call signUp first
To fix this, you will need to change:
var user = PFUser()
To the following:
var user = PFUser.currentUser()!
The rest of your code (for example user["location"] = locationTextField.text) works fine and will dynamically/lazily add a new column to your User database (which is what you want).

Parse allows you to add columns to a class lazily, meaning that you can add a field to your PFObject and if it is not present in your Parse class, Parse will add that column for you.
Here's example how you would add a column via code:
// Add the new field to your object
yourObject["yourColumnName"] = yourValue
yourObject.saveInBackground()
You'll notice that Parse will create a new column named yourColumnName on their web portal.
reference from HERE.

Related

Facebook login using Firebase - Swift iOS

I'm implementing login with Facebook using Firebase, I have this code which searches my database after a successful facebook authentication for the email if exists in database and logs in the app if found, I want to direct the user to registration view controller if not found but its not working since this method is asynchronous. I appreciate if anyone can help. Here is my code :
func getFacebookUserInfo() {
if(FBSDKAccessToken.current() != nil){
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "id,name,gender,email,education"])
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) -> Void in
let data = result as! [String : AnyObject]
let email = data["email"] as? String
let emailRef = FIRDatabase.database().reference().child("usernameEmailLink")
emailRef.queryOrderedByValue().observe(.childAdded, with: { snapshot in
if let snapshotValue = snapshot.value as? [String: AnyObject] {
for (key, value) in snapshotValue {
if(value as? String == email){
self.stringMode = snapshotValue["mode"]! as! String
self.username = key
self.parseUserInfoFromJSON()
return
}
}
}
})
})
connection.start()
}
}
Thank you.
The registration/existence of the user in Firebase should probably be determined before the graphRequest code in the question.
Most importantly, (and this is critical), email addresses are dynamic so they should not be used to verify if a user exists. i.e. user with email address of 'leroy#gmail.com' updates his email to 'leroy.j#gmail.com'. If emails are used to verify registration, it can totally break if that email changes.
Please use Firebase uid's for that purpose as they are static and unique.
Since we only have a small snippet of code, we don't know the exact sequence being used. This answer is pseudo-code to outline a possible sequence.
We assume that by 'registered' it means that the user has gone through some kind of app registration sequence and the user has been created (and now exists/is registered) in Firebase.
In general there would be a login button and a delegate method to handle the actual login action.
The user enters their login and taps the login button
func loginButton(loginButton: FBSDKLoginButton!,
didCompleteWithResult result: FBSDKLoginManagerLoginResult!,
error: NSError?) {
Firebase can then get the credentials for that user (see Firebase doc quote below)
let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
At that point, sign in the user and check to see if they are registered (exist) in the Firebase user node.
FIRAuth.auth()?.signIn(with: credential) { (user, error) in
if let error = error { //failed due to an error
return
}
let uid = user.uid //the firebase uid
let thisUserRef = userRef.child(uid) //a reference to the user node
//check to see if the user exists in firebase (i.e. is Registered)
thisUserRef.observeSingleEvent(of: .value, with: { (snapshot) in
//if snapshot exists
//then the user is already 'registered' in the user node
// so continue the app with a registered user
//if not, then need to have the user go through a registration sequence and
// then create the user (make them registered) in the user node
doRegisterUser(user)
})
func doRegisterUser(user: FIRUser) {
//get what you need from the user to register them
// and write it to the users node. This could be from additional
// questions or from their Facebook graph, as in the code in the
// question
//for this example, we'll just write their email address
let email = user.email
let dict = ["email": email]
//create a child node in the users node with a parent of uid
// and a child of email: their email
thisUserRef.setValue(node)
//next time the user logs in via FB authentication, their user node
// will be found as they are now a 'registered' user
}
From the Firebase docs
After a user signs in for the first time, a new user account is
created and linked to the credentials—that is, the user name and
password, or auth provider information—the user signed in with. This
new account is stored as part of your Firebase project, and can be
used to identify a user across every app in your project, regardless
of how the user signs in.
As I mentioned, this is very pseudo code but offers a possible sequence for a solution.

Add Extra Parse Log In Field

I am making an app that logs you in to a certain group, Currently I have it where you log in as such:
let loginUser = PFUser()
loginUser.username = username.text!
loginUser.password = password.text!
PFUser.logInWithUsername(inBackground: loginUser.username!, password: loginUser.password!, block: { (user, error) in
if user != nil { //Continue with code
but what I'd like to do would be to add in my group login ID field so that I do not have to make an additional call to match their groupID TextField with their currently set up groupID. I don't know if you can and I couldn't find it in documentation. Something Like:?
let loginUser = PFUser()
loginUser.username = username.text!
loginUser.password = password.text!
loginUser["groupID"] = groupID.text!
PFUser.logInWithUsername(inBackground: loginUser.username!, password: loginUser.password!, login["groupID"]: login.groupID block: { (user, error) in
if user != nil { //Now Checks login AND for group id...
Now obviously I know it's not that easy but does anybody have a mildly easy work around for this? Right now afterwords i'm comparing the
user["groupID"] == groupID.text! {
// Then Login to group is a success!
// Segue to next View Controller
} else {
// Let the user know the Log In was "unsuccessful" even though they logged in but they got their groupID wrong
// Log User Out
// Clear groupID Text Field & Display alert so they can reattempt log in
}
Any help would be appreciated!
Thanks!
I suggest you to use "cloud code", you might want to create your own login method using some other language like javascript.

Entering Zip Code Switchies View Controller If Found In Parse (Swift and XCode)

So I'm trying to create a registration page with availability by Zip Code.
For instance, a user can only register if the service is available in their area (zip code).
So far I have a Text field for Zip Code and a button labeled "Check Availability".
I have a Parse Backend and I tested a connection to it using their setup guide and it works.
How can I go about adding Zip Codes to Parse and when a user types in that zip code that matches it'll open a new View Controller and they can register.
First method is to save zipCode that the user entered from the TextField:
var zipcodeFromUsers = customTextfield.text.toInt()
var savingObject = PFObject(className: "nameoftheclass")
savingObject["username"] = PFUser.currentUser()?.username
savingObject["zipcode"] = zipcodeFromUsers
savingObject.saveEventually { (success:Bool, error:NSError?) -> Void in
if error == nil
{
// data was saved
}
}
Second Method is to retrieve all the zipcodes from parse. So lets say that we want to query all 2344 zip codes
var needToFoundZipcode = 2344
var queryFromParse = PFQuery(className: "nameoftheclass")
queryFromParse.whereKey("zipcode", equalTo: needToFoundZipcode)
queryFromParse.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil
{
if let objects = objects as? [PFObject]
{
for SingleZipcode in objects
{
var singlezipcodeFound = SingleZipcode["zipcode"] as! Int
// now you could whatever you want
}
}
}
}

ACL Role for admin in parse swift

Struggling to get this working, lack of understanding, but if anyone could help me to get there, that would be great. Currently I have a user logging in as an administrator by just setting a boolean, this works fine:
if (authority == "true"){
let acl = PFACL(user: PFUser.currentUser()) // Only user can write
acl.setPublicReadAccess(true) // Everybody can read
acl.setWriteAccess(true, forUser: PFUser.currentUser()) // Also
var role:PFRole = PFRole(name: "Administator", acl: acl)
role.users.addObject(PFUser.currentUser())
role.saveInBackground()
self.activityIndicator.stopAnimating()
let vc : AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("Admin")
self.showViewController(vc as UIViewController, sender: vc)
}
This sets an admin role in my parse database. What I am trying to do is to give privileges to this user so that he could edit all other users e.g. giving points to the students for the correctly completed tasks.
if let object = userObject?{
println(tasksCorrect)
object["tasksCorrect"] = tasksCorrect + 1
println(object)
object.saveInBackground()}
You need to ensure that user objects have an ACL that includes read/write access for the "Administrator" role.

How to check if a user upgraded using parse?

My app has a login and signup. Once the user is logged in he can then choose to upgrade the account. When the account is upgraded, a new class in parse is created called "Upgrade". Here it has a bunch of subclasses with stored information. Then once the user is upgraded it brings him to a special page that only upgraded users have access to. But how can I check on login if the user is upgraded, and if he is, automatically bring him to the special page.
In my parse, I have the User information stored with subclasses "Username" and "Password". Then in a separate class I have the upgrade information stores with subclasses "Address", "Phone Number", and I have a linker to link back to the user who created it.
my current code for login is:
#IBAction func loginButton(sender:AnyObject) {
var username = self.usernameTextField.text
var password = self.passwordTextField.text
if(password.utfCount <5) {
var alert = UIAlertView(title:"Invalid", message: "Password must be greater than 5", delegate: self, cancelButtonTitle:"OK")
}
else {
PFUser.logInWithUsernameInBackground(username, password: password, block:{(user, error) -> Void in
if ((user != nil) {
self.performSegueWithIdentifier("LoginSegue", sender: nil)
This is the basic code but it does not check to see if the user is upgraded.
I tried:
if(PFUser.currentUser() == PFQuery(className:"Upgrade")) {
self.performSegueWithIdentifier("UpgradedSegue")
But obivously this didnt work due to the current user not equaling that class.
What kind of code could I user to check if the user made a Upgrade class within parse?
I have tried messing around with fetchinbackground code and enter code hereobjectinbackground but I can't seem to make those work.
I don't know the Swift very well, so sorry if there are errors, but try something like:
var query = PFQuery(className:"Upgrade")
query.whereKey("user", equalTo:currentUser.objectId)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject!, error: NSError!) -> Void in
if error != nil
println("The getFirstObject request failed.")
} else if object == nil{
//No Upgrade object with that user's ID
} else {
// The find succeeded, user has created an Upgrade object
println("Successfully retrieved the object.")
}
}
You could also set up your code to store the pointer to the Upgrade object on the user, rather than the other way around. You could set a bool value on the user to see if they have upgraded. If it is true, then take them to the upgrade screen, or fetch the Upgrade object, whatever you need first.

Resources