navigation controller doesn't work - swift

Signup UIViewController design that validates email, password and confirm password.
Signup is embedded in NavigationController
func showAlert(ttl:String,msg:String){
let alert = UIAlertController(title: "\(ttl)", message: "\(msg)", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
#IBAction func signUp(_ sender: UIButton) {
if (email.text != nil && password.text != nil && confrimPassword.text != nil){
if !(isValidEmail(testStr: email.text!)){
showAlert(ttl: "Invaild Email-ID", msg: "Please enter an valid Email-ID")
}
else if !(isValidPassword(testStr: password.text)){
showAlert(ttl: "Invalid Password", msg: "Password must have at least one uppercase,one digit,one lowercase and minimum 8 characters")
}
else if !(passwordMatch(password: password.text!, confirmPassword: confrimPassword.text!)){
showAlert(ttl: "Passwords doesn't Match", msg: "Please re-enter your password")
}
else{
if Connectivity.isConnectedToInternet {
Authentication.Signup(for: email.text!, password: password.text!,finished: { resdata in do{ let res = try JSONSerialization.jsonObject(with: resdata) as! Dictionary<String, AnyObject>
print(res)
DispatchQueue.main.async {
let view: Verification = self.storyboard?.instantiateViewController(withIdentifier: "Verify") as! Verification
view.email = self.email.text!
//doesnot work
self.navigationController?.pushViewController(view, animated: true)
}
}
catch{
print("Error")
}
})
}
else{
showAlert(ttl: "No Internet", msg: "Please check your internet connection")
}
}
}
else{
self.showAlert(ttl: "Enter all Credentials", msg: " ")
}
}
}
Tried using segue also that doesn't suit my requirements

#IBAction func signUp(_ sender: UIButton) {
Authentication.Signup(for: email.text!, password: password.text!,finished: { resdata in do{
let res = try JSONSerialization.jsonObject(with: resdata) as! Dictionary<String, AnyObject>
print(res)
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "Verify") as! Verification
controller.email = self.email.text!
self.present(controller, animated: true, completion: nil)
}
}

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

PARSE user still active after log-out

I'm learning to use Parse Server to manage users and passwords. I have an app that lets the user log-in and store information in the server (age, weight, gender and name). But I'm having a problem, if the user logs out, the app takes them to the login page and, if after that they use a non-existing user or incorrect password, after showing the alert "Incorrect user or password", the app takes them to the main page with the previous user information. I'm not sure what is going on; the code I'm using to log in is this:
#IBAction func signInButton(_ sender: Any) {
let acl = PFACL()
acl.getPublicWriteAccess = true
PFUser().acl = acl
if userTextField.text == "" || passwordTextField.text == "" {
createAlert(title: "Error", message: "Both fields should be filled")
} else {
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents() // UIApplication.shared() is now UIApplication.shared
PFUser.logInWithUsername(inBackground: userTextField.text!, password: passwordTextField.text!, block: { (user, error) in
self.activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents() // UIApplication.shared() is now UIApplication.shared
if error != nil {
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Login Error", message: displayErrorMessage)
} else {
print("Logged in")
let usuario = PFUser.current()
let dataUse = self.queryDownload(usuario: usuario!)
for items in dataUse {
let dataMeassure: GlucoseEvents = NSEntityDescription.insertNewObject(forEntityName: "GlucoseEvents", into: DatabaseController.getContext()) as! GlucoseEvents
dataMeassure.allAtributes = items
}
DatabaseController.saveContext()
self.performSegue(withIdentifier: "goToMain", sender: self)
}
})
}
}
Now, this problem only happens after the logout, so I'm guessing the error in that function. The code of the logout is:
#IBAction func logOut(_ sender: Any) {
let refreshAlert = UIAlertController(title: "Confirm", message: "Really LogOut?", preferredStyle: UIAlertControllerStyle.alert)
refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in
PFUser.logOutInBackground { (error) in
if error != nil {
self.createAlert(title: "Error", message: "Error")
}
}
self.performSegue(withIdentifier: "closedProf", sender: self)
}))
refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in
print("Handle Cancel Logic here")
}))
present(refreshAlert, animated: true, completion: nil)
}
Is there another way to logout and avoid this problem? Thanks
More info
So I tried to see if the problem was the server not returning a nil user. And added a print statement to the logout. Turns out that it's nil so I don't know why it is being stored (or where) but the LogOut returns a nil user.

How to store value and retrive it to use in next view controller after login using userdefaults?

I want to store the ngoid value in userDefaults so that I can access it in my next API call in the next viewController class. How do I do it?
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! Int!
let ngoid = json.value(forKey: "NgoId") as? String
print(ngoid ?? "")
let defaults = UserDefaults.standard
defaults.set(ngoid, forKey: "ngoid")
print(ngoid!)
DispatchQueue.main.async {
self.alert = UIAlertController(title: "Alert Box!", message: "\(msg)", preferredStyle: .alert)
self.action = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
let vtabbar1 = self.storyboard?.instantiateViewController(withIdentifier: "tabbar1")
self.navigationController?.pushViewController(vtabbar1!, animated: true)
}
self.alert.addAction(self.action)
self.present(self.alert, animated: true, completion: nil)
}
}
}
catch let error {
print(error)
}
}
task.resume()
}
You could use UserDefaults but if you only need to use the value on the next viewController you should use a segue for this purpose. Here is a guide of how that works. Otherwise use UserDefaults like the example below:
// To set the value
UserDefaults.standard.set(ngoid, forKey: "NgoId")
// To get the value
let id = UserDefaults.standard.string(forKey: "NgoId")
This is not a best way to save in user default and then use in next ViewController, use this overdid method
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowCounterSegue"
{
if let destinationVC = segue.destinationViewController as? OtherViewController {
destinationVC.ngoid = ngoid
}
}
}
use ngoid anywhere in your next ViewController api call.

Show Login/Signup Errors with firebase

I want to show the error to the user while logging in if the information is incorrect. Such as invalid username/Password etc
#IBAction func signIn(_ sender: Any) {
Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!) { (user, error) in
if error != nil {
//self.createAlert(titleText: "Error", messageText: String(describing: error?.localizedDescription))
return
} else {
self.performSegue(withIdentifier: "signInToTabBarVC", sender: nil)
print("Signed In")
}
}
}
I also want to show sign up errors. Including email is already in use or username or password is too weak
Auth.auth().createUser(withEmail: emailField.text! , password: passwordField.text!, completion: { (user: User?, error: Error?) in
if error != nil {
print(error!.localizedDescription)
return
}
let uid = user?.uid
let storageRef = Storage.storage().reference(forURL: "gs://vloggle-cb375.appspot.com").child("profile_picture").child(uid!)
if let chosenImg = self.chosenImage, let imageData = UIImageJPEGRepresentation(chosenImg, 0.1) {
storageRef.putData(imageData, metadata: nil, completion: { (metadata, error) in
if error != nil {
return
}
let profileImageUrl = metadata?.downloadURL()?.absoluteString
self.setUserInformation(profileImageUrl: profileImageUrl!, username: self.usernameField.text!, email: self.emailField.text!, uid: uid!)
})
}
})
}
you can show error message with the help of UIAlertView
let dialog = UIAlertController(title: error!.localizedDescription, message: "", preferredStyle: UIAlertControllerStyle.alert)
dialog.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
DispatchQueue.main.async(execute: {
self.present(dialog, animated: true, completion: nil)
})