Best way to combine mysql and Facebook sign up/in - swift

There are two ways how to sign up to my iOS app. First option is using mysql/php (user types email,username,password and I store that in mysql database.
Second option is log in using Facebook and here starts my problem , because I need to have userId, which I can get from Facebook, but I also have an Id in my MySQL database(every user should have his own Id).
So my question is what would you recommend me to do. I have tried to store Facebook user to mysql so he received his unique Id.(but then there were empty columns like password, because Facebook user does not need password).
This is my Facebook sign in (when I sign in with my Facebook account it is ok because my Facebook id Is a pretty high number):
#IBAction func btnFBLoginPressed(sender: AnyObject) {
loadingIndicator.startAnimating()
FBSDKLoginManager().logInWithReadPermissions(["public_profile", "email"],
fromViewController:self,
handler: { (result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if (error == nil){
self.getFBUserData()
self.loadingIndicator.stopAnimating()
}else{
self.loadingIndicator.stopAnimating()
let myAlert = UIAlertController(title: "Alert!", message: error.localizedDescription, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
print(error.localizedDescription)
print("error")
return
}
})
}
func getFBUserData(){
if((FBSDKAccessToken.currentAccessToken()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil){
print(result)
print(result["name"])
print(result["id"])
NSUserDefaults.standardUserDefaults().setObject(result["name"]!, forKey: "username")
NSUserDefaults.standardUserDefaults().setObject(result["id"]!, forKey: "userId")
NSUserDefaults.standardUserDefaults().synchronize()
let firstPage = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController")as! ViewController
let appDelegate = UIApplication.sharedApplication().delegate
appDelegate?.window??.rootViewController = firstPage
}else{
let myAlert = UIAlertController(title: "Alert!", message: error?.localizedDescription, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
print(error.localizedDescription)
print("error")
return
}
})
}
}
This is MySQL sign in:
#IBAction func loginTapped(sender: AnyObject) {
let userEmail = emailTextField.text
let userPassword = passwordTextField.text
if (userEmail!.isEmpty||userPassword!.isEmpty){
let myAlert = UIAlertController(title: "Alert", message: "All fields must be filled out", preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
return
}
self.loadingIndicator.startAnimating()
let myUrl = NSURL(string: "http://localhost/~myPc/userSignIn.php")!
let request = NSMutableURLRequest(URL: myUrl)
request.HTTPMethod = "POST"
let postString = "userEmail=\(userEmail!)&userPassword=\(userPassword!)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in
dispatch_async(dispatch_get_main_queue()){
if (error != nil){
let myAlert = UIAlertController(title: "Alert", message: error?.localizedDescription, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
self.loadingIndicator.stopAnimating()
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
if let parseJson = json {
let userId = parseJson["userId"] as? String
if userId != nil{
NSUserDefaults.standardUserDefaults().setObject(parseJson["username"], forKey: "username")
NSUserDefaults.standardUserDefaults().setObject(parseJson["userId"], forKey: "userId")
NSUserDefaults.standardUserDefaults().synchronize()
let firstPage = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController")as! ViewController
let appDelegate = UIApplication.sharedApplication().delegate
appDelegate?.window??.rootViewController = firstPage
}else{
let userMessage = parseJson["message"] as? String
let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
self.loadingIndicator.stopAnimating()
}
self.loadingIndicator.stopAnimating()
}
} catch {
print(error)
}
}
}).resume()
}

Related

How to add another key/value to Firebase Array

The problem that I'm facing is that I have successfully created the array and have displayed the values like so:
Users
-uid
- Name: Example
- Profile Pic URL: example12345
- email: example#example.co.uk
However, in another swift file I have successfully generated a personality type and am struggling to add this to the array so that I end up with something that looks like this:
Users
-uid
- Name: Example
- Profile Pic URL:
- email: example#example.co.uk
- personality type: INTJ
I have tried copying the code from the previous swift class to no avail
This is the code for the working firebase array
#IBAction func createAccountAction(_ sender: AnyObject) {
let usersRef = Database.database().reference().child("Users")
let userDictionary : NSDictionary = ["email" : emailTextField.text!, "Name": nameTextField.text!]
if emailTextField.text == "" {
let alertController = UIAlertController(title: "Error", message: "Please enter your email and password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().createUser(withEmail: self.emailTextField.text ?? "", password: self.passwordTextField.text ?? "") { (result, error) in
if error != nil {
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
return
}
guard let user = result?.user else { return }
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.present(vc, animated: true, completion: nil)
// HERE YOU SET THE VALUES
usersRef.child(user.uid).setValue(userDictionary, withCompletionBlock: { (error, ref) in
if error != nil { print(error); return }
let imageName = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).png")
if let profileImageUrl = self.profilePicture.image, let uploadData = UIImageJPEGRepresentation(self.profilePicture.image!, 0.1) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil, metadata != nil {
print(error ?? "")
return
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!.localizedDescription)
return
}
if let profileImageUrl = url?.absoluteString {
self.addImageURLToDatabase(uid: user.uid, values: ["profile photo URL": profileImageUrl as AnyObject])
}
})
})
}
}
)}
}
}
This is the other swift file function which generates the personality type which I would like to add to the array
#IBAction func JPbtn(_ sender: Any) {
if (Judging < Perceiving){
Result3 = "P"
} else {
Result3 = "J"
}
let PersonalityType = "\(Result) \(Result1) \(Result2) \(Result3)"
print(PersonalityType)
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Example") as! ViewController
self.present(vc, animated: true, completion: nil)
}
So if you are just trying to add a new key with a value, all you need to do is create a new reference like this.
guard let currentUserUID = Auth.auth().currentUser?.uid else { return }
print(currentUserUID)
let userPersonalityRef = Database.database().reference().child("users").child(currentUserUID).child("personality")
userPersonalityRef.setValue("Some Value")
When you set the value it can also be a dictionary if you want. But if your users don't all have personality make sure it optional on your data model or else It might crash your app. When you are getting your user from firebase.

Unable to merge two firebase arrays in Firebase Database

Hello I am relatively new to Swift/Firebase and I am struggling to merge two arrays so that the downloadURL is seen amongst both the name and the email fields. One function adds the name and the email through the button click the other is another function to save the URL. When I try and merge them I get this (as seen in the image below). Here is my code:
#IBAction func createAccountAction(_ sender: AnyObject) {
let Users = Database.database().reference().child("Users")
let userDictionary : NSDictionary = ["email" : emailTextField.text as String!, "Name": nameTextField.text!]
Users.childByAutoId().setValue(userDictionary) {
(error, ref) in
if self.emailTextField.text == "" {
let alertController = UIAlertController(title: "Error", message: "Please enter your email and password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().createUser(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
print("You have successfully signed up")
//Goes to the Setup page which lets the user take a photo for their profile picture and also chose a username
var imgData: NSData = NSData(data: UIImageJPEGRepresentation((self.profilePicture?.image)!, 0.8)!)
self.uploadProfileImageToFirebase(data: imgData)
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.present(vc, animated: true, completion: nil)
} else {
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
}
func addImageURLToDatabase(uid:String, values:[String:AnyObject]){
let Users = Database.database().reference().child("Users")
let ref = Database.database().reference(fromURL: "https://example.firebaseio.com/")
Users.updateChildValues(values) { (error, ref) in
if(error != nil){
print(error)
return
}
self.parent?.dismiss(animated: true, completion: nil)
}
}
Something like this is what you want. I removed a few variables from your function but you can add them back. I just wanted to make sure the code compiles.
#IBAction func createAccountAction(_ sender: AnyObject) {
let usersRef = Database.database().reference().child("Users")
let userDictionary : NSDictionary = ["email" : emailTextField.text!, "Name": nameTextField.text!]
if emailTextField.text == "" {
let alertController = UIAlertController(title: "Error", message: "Please enter your email and password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
} else {
Auth.auth().createUser(withEmail: self.emailTextField.text ?? "", password: self.passwordTextField.text ?? "") { (result, error) in
if error != nil {
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
return
}
guard let user = result?.user else { return }
// HERE YOU SET THE VALUES
usersRef.child(user.uid).setValue(userDictionary, withCompletionBlock: { (error, ref) in
if error != nil { print(error); return }
self.addImageURLToDatabase(uid: user.uid, values: ["Put": "Your Values Here" as AnyObject])
})
}
}
}
func addImageURLToDatabase(uid:String, values:[String:AnyObject]){
let usersRef = Database.database().reference().child("Users").child(uid)
usersRef.updateChildValues(values) { (error, ref) in
if(error != nil){
print(error)
return
}
self.parent?.dismiss(animated: true, completion: nil)
}
}

iOS swift 3.0 Json parsing and alert issue

I'm working on login form. I'm a fresher on iOS development.
After successful login, I want to show an alert after completion of json parsing. I've parsed Ngoid inside a do while block. Now I want to pass the value "Ngoid" to the next view controller so that it can be used to fetch the further data.
Main Problem: Here is the code I have written and it gives me error to write alert it on main thread only.
As I want the "Ngoid" value for further use there, so how should I write it and what is the correct way to execute the code?
Here is the code I have written:
#IBAction func loginbutton(_ sender: Any) {
let myUrl = NSURL(string: "http://www.shreetechnosolution.com/funded/ngo_login.php")
let request = NSMutableURLRequest(url:myUrl! as URL)
request.httpMethod = "POST"// Compose a query string
let postString = "uname=\(textfieldusername.text!)&password=\(textfieldpassword.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){ data , response , error in
if error != nil
{
//let alert = UIAlertView()
let alert = UIAlertController(title: "Alert Box !", message: "Login Failed", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
return
}
// You can print out response object
print("*****response = \(String(describing: response))")
let responseString = NSString(data: data! , encoding: String.Encoding.utf8.rawValue )
if ((responseString?.contains("")) == nil) {
print("incorrect - try again")
let alert = UIAlertController(title: "Try Again", message: "Username or Password Incorrect", preferredStyle: .alert)
let yesAction = UIAlertAction(title: "Nochmalversuchen", style: .default) { (action) -> Void in
}
// Add Actions
alert.addAction(yesAction)
// Present Alert Controller
self.present(alert, animated: true, completion: nil)
}
else {
print("correct good")
}
print("*****response data = \(responseString!)")
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary {
if let email = json["UserName"] as? String,
let password1 = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
let msg = (json.value(forKey: "message") as! NSString!) as String
let id = (json.value(forKey: "NgoId") as! NSString!) as String
// let alert : UIAlertView = UIAlertView(title: "Alert box!", message: "\(msg!).",delegate: nil, cancelButtonTitle: "OK")
// alert.show()
self.alert = UIAlertController(title: "Alert Box!", message: "\(msg)", preferredStyle: .alert)
print("the alert\(self.alert)")
self.action = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
let viewControllerYouWantToPresent = self.storyboard?.instantiateViewController(withIdentifier: "pass1") as! ViewControllerngodetails
viewControllerYouWantToPresent.temp1 = self.id
self.present(viewControllerYouWantToPresent, animated: true, completion: nil)
}
self.alert.addAction(self.action)
self.present(self.alert, animated: true, completion: nil)
}
}catch let error {
print(error)
}
}
task.resume()
}
A pro tip:
All your UI related tasks need to be done in the main thread. Here you are presenting the alert inside a closure which executes in a background thread, thats the problem. You need to call the main queue and present alert in that block.
EDIT:
Just put your alert code in this-
For Swift 3-
Get main queue asynchronously
DispatchQueue.main.async {
//Code Here
}
Get main queue synchronously
DispatchQueue.main.sync {
//Code Here
}
Every UI update has to be on main thread:
#IBAction func loginbutton(_ sender: Any) {
let myUrl = NSURL(string: "http://www.shreetechnosolution.com/funded/ngo_login.php")
let request = NSMutableURLRequest(url:myUrl! as URL)
request.httpMethod = "POST"// Compose a query string
let postString = "uname=\(textfieldusername.text!)&password=\(textfieldpassword.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){ data , response , error in
if error != nil
{
DispatchQueue.main.async {
let alert = UIAlertController(title: "Alert Box !", message: "Login Failed", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
// Present Alert Controller
self.present(alert, animated: true, completion: nil)
}
return
}
// You can print out response object
print("*****response = \(String(describing: response))")
let responseString = NSString(data: data! , encoding: String.Encoding.utf8.rawValue )
if ((responseString?.contains("")) == nil) {
print("incorrect - try again")
DispatchQueue.main.async {
let alert = UIAlertController(title: "Try Again", message: "Username or Password Incorrect", preferredStyle: .alert)
let yesAction = UIAlertAction(title: "Nochmalversuchen", style: .default) { (action) -> Void in }
// Add Actions
alert.addAction(yesAction)
// Present Alert Controller
self.present(alert, animated: true, completion: nil)
}
}
else {
print("correct good")
}
print("*****response data = \(responseString!)"
do {
//create json object from data
if let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary {
if let email = json["UserName"] as? String,
let password1 = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
let msg = (json.value(forKey: "message") as! NSString!) as String
let id = (json.value(forKey: "NgoId") as! NSString!) as String
DispatchQueue.main.async {
self.alert = UIAlertController(title: "Alert Box!", message: "\(msg)", preferredStyle: .alert)
print("the alert\(self.alert)")
self.action = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
let viewControllerYouWantToPresent = self.storyboard?.instantiateViewController(withIdentifier: "pass1") as! ViewControllerngodetails
viewControllerYouWantToPresent.temp1 = self.id
self.present(viewControllerYouWantToPresent, animated: true, completion: nil)
}
self.alert.addAction(self.action)
self.present(self.alert, animated: true, completion: nil)
}
}
}catch let error {
print(error)
}
}
task.resume()
}

AWS Cognito getSession

I am trying log users as simply as possible using the signup and getSession function.
I have not encountered difficulties in using the signup function to create new users in my cognate user pool.
When I try to create a function for logging, I try this code :
func signin(){
let pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolSignInProviderKey)
let user = pool.getUser("toto")
user.getSession("toto", password: "BabaBobo1&", validationData: nil).continueWith(block: {[weak self] (task) -> Any? in
DispatchQueue.main.async {
if let error = task.error as? NSError {
let alertController = UIAlertController(title: error.userInfo["__type"] as? String,
message: error.userInfo["message"] as? String,
preferredStyle: .alert)
let retryAction = UIAlertAction(title: "Retry", style: .default, handler: nil)
alertController.addAction(retryAction)
self?.present(alertController, animated: true, completion: nil)
}else if let session = task.result {
let alertController = UIAlertController(title: "token",
message: session.accessToken?.tokenString,
preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self?.present(alertController, animated: true, completion: nil)
}
}
return nil
})
}
It appears that the trailing block is never executed. Does anyone knows what I am doing wrong ?
My aim is to reduce the AWS linked code to the minimum. I want to avoid as much as possible to use the different delegate protocols provided in the SDK

Swift UIAlert - get data from dataTaskWithRequest

i need the variable 'response' to be taken from "dataTaskWithRequest". Right now, 'response' is not found because it is outside of the brackets. How can i make sure to pass the response variable to the UIAlert? Thanks
Here is my code:
#IBAction func buttonCreateAccount(sender: AnyObject) {
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.example.com/createaccount.php")!)
request.HTTPMethod = "POST"
let postString = "user_name=\(username.text!)&email=\(email.text!)&password=\(password.text!)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let response = String(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(response)")
}
task.resume()
//problem is here. 'response' variable cannot be taken from above. i need it to be taken from above.
if response == "Username taken" {
if let getModernAlert: AnyClass = NSClassFromString("UIAlertController") { // iOS 8
let myAlert: UIAlertController = UIAlertController(title: "Registration", message: response, preferredStyle: .Alert)
myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(myAlert, animated: true, completion: nil)
} else { // iOS 7
let alert: UIAlertView = UIAlertView()
alert.delegate = self
alert.title = "Registration"
alert.message = "Testing"
alert.addButtonWithTitle("OK")
alert.show()
}
} else {
if let getModernAlert: AnyClass = NSClassFromString("UIAlertController") { // iOS 8
let myAlert: UIAlertController = UIAlertController(title: "Registration", message: response, preferredStyle: .Alert)
myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(myAlert, animated: true, completion: nil)
} else { // iOS 7
let alert: UIAlertView = UIAlertView()
alert.delegate = self
alert.title = "Registration"
alert.message = "Testing"
alert.addButtonWithTitle("OK")
alert.show()
self.dismissViewControllerAnimated(true, completion: {});
}
}
}
dataTaskWithRequest runs asynchronously. You will not get the response immediately. Separate it into two functions:
#IBAction func buttonCreateAccount(sender: AnyObject) {
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.example.com/createaccount.php")!)
request.HTTPMethod = "POST"
let postString = "user_name=\(username.text!)&email=\(email.text!)&password=\(password.text!)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let response = String(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(response)")
// Now that the response is ready, call the other function to handle it
handleResponse(response)
}
task.resume()
}
func handleResponse(response: String) {
if response == "Username taken" {
if let getModernAlert: AnyClass = NSClassFromString("UIAlertController") { // iOS 8
let myAlert: UIAlertController = UIAlertController(title: "Registration", message: response, preferredStyle: .Alert)
myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(myAlert, animated: true, completion: nil)
} else { // iOS 7
let alert: UIAlertView = UIAlertView()
alert.delegate = self
alert.title = "Registration"
alert.message = "Testing"
alert.addButtonWithTitle("OK")
alert.show()
}
} else {
if let getModernAlert: AnyClass = NSClassFromString("UIAlertController") { // iOS 8
let myAlert: UIAlertController = UIAlertController(title: "Registration", message: response, preferredStyle: .Alert)
myAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(myAlert, animated: true, completion: nil)
} else { // iOS 7
let alert: UIAlertView = UIAlertView()
alert.delegate = self
alert.title = "Registration"
alert.message = "Testing"
alert.addButtonWithTitle("OK")
alert.show()
self.dismissViewControllerAnimated(true, completion: {});
}
}
}