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)
}
}
Related
I'm present a alert when I click the button. I choose from a list (if how much data is available.) How can I save my data choose from a list index?
You can see UI in here
My AccountServices
class AccountServices {
static let databaseReference = Database.database().reference(withPath: "Accounts").child((Auth.auth().currentUser?.uid)!)
static var account = Account()
static func saveChanges() {
databaseReference.setValue(try! FirebaseEncoder().encode(AccountServices.account))
}
static func getAccount() {
databaseReference.observeSingleEvent(of: .value, andPreviousSiblingKeyWith: { (snapshot, _) in
account = try! FirebaseDecoder().decode(Account.self, from: snapshot.value!)
})
}
}
Variable
var product: ProductViewModel?
addButton Tapped
#IBAction func addToCartButtonTapped(_ sender: UIButton) {
let alert = UIAlertController(title: "Bu ürünü hangi sepetinize eklemek istersiniz ?", message: "", preferredStyle: .actionSheet)
var indexer = 0
for cart in AccountServices.account.cart! {
if cart.product == nil{
AccountServices.account.cart![indexer].product = [Product]()
}
let action = UIAlertAction(title: cart.name , style: .default, handler: { (sender) in
if let index = alert.actions.firstIndex(where: { $0 === sender }) {
AccountServices.account.cart?[index].product?.append(self.product) `//Error: Cannot convert value of type 'ProductViewModel?' to expected argument type 'Product'`
AccountServices.saveChanges()//TODO...
}
let addAlert = UIAlertController(title: "Sepetinize Eklendi.", message: "Ürününüz sepetinize eklendi.", preferredStyle: .alert)
let okButton = UIAlertAction(title: "Tamam", style: .default, handler: nil)
addAlert.addAction(okButton)
self.present(addAlert, animated: true, completion: nil)
})
alert.addAction(action)
indexer += 1
}
let cancelaction = UIAlertAction(title: "Vazgeç", style: .cancel, handler: nil)
alert.addAction(cancelaction)
present(alert, animated: true, completion: nil)
}
}
I would like to add the ability to register with the phone number while registering. I wrote a function but it doesn't work. Can you examine the code? What should I do?
func sendCode(_ sender: Any) {
let alert = UIAlertController(title: "Phone number", message: "Is this your phone number? \n \(emailField.text!)", preferredStyle: .alert)
let action = UIAlertAction(title: "Yes", style: .default) { (UIAlertAction) in
PhoneAuthProvider.provider().verifyPhoneNumber(self.emailField.text!, uiDelegate: nil) { (verificationID, error) in
if error != nil {
print("eror: \(String(describing: error?.localizedDescription))")
} else {
let defaults = UserDefaults.standard
defaults.set(verificationID, forKey: "authVID")
let navController = UINavigationController(rootViewController: CodeEntryView())
self.present(navController, animated: true, completion: {
})
}
}
}
let cancel = UIAlertAction(title: "No", style: .cancel, handler: nil)
alert.addAction(action)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
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.
My photo app crashes when user selects video. The user can select photo and it works fine, but I'd like to remove the option to take a video. How do I disable video? The relevant chunk of code is below...
#IBAction func choosePhoto(_ sender: UIButton) {
let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .actionSheet)
imagePicker = UIImagePickerController()
imagePicker.delegate = self
if (UIImagePickerController.isSourceTypeAvailable(.camera)) {
let cameraAction = UIAlertAction(title: "Use Camera", style: .default) { (action) in
let status = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
if (status == .authorized) {
self.displayPicker(type: .camera)
}
if (status == .restricted) {
self.handleRestricted()
}
if (status == .denied) {
self.handleDenied()
}
if (status == .notDetermined) {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted) in
if (granted) {
self.displayPicker(type: .camera)
}
})
}
}
alertController.addAction(cameraAction)
}
if (UIImagePickerController.isSourceTypeAvailable(.photoLibrary)) {
let photoLibraryAction = UIAlertAction(title: "Use Photo Library", style: .default) { (action) in
let status = PHPhotoLibrary.authorizationStatus()
if (status == .authorized) {
self.displayPicker(type: .photoLibrary)
}
if (status == .restricted) {
self.handleRestricted()
}
if (status == .denied) {
self.handleDenied()
}
if (status == .notDetermined) {
PHPhotoLibrary.requestAuthorization({ (status) in
if (status == PHAuthorizationStatus.authorized) {
self.displayPicker(type: .photoLibrary)
}
})
}
}
alertController.addAction(photoLibraryAction)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
func handleDenied() {
let alertController = UIAlertController(title: "Camera Access Denied", message: "This app does not have acces to your device's camera. Please update your settings.", preferredStyle: .alert)
let settingsAction = UIAlertAction(title: "Go To Settings", style: .default) { (action) in
DispatchQueue.main.async {
UIApplication.shared.open(NSURL(string: UIApplicationOpenSettingsURLString)! as URL)
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.popoverPresentationController?.sourceView = self.photoImage
alertController.popoverPresentationController?.sourceRect = self.photoImage.bounds
alertController.addAction(settingsAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
func handleRestricted() {
let alertController = UIAlertController(title: "Camera Access Denied", message: "This device is restricted from accessing the camera at this time", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.popoverPresentationController?.sourceView = self.photoImage
alertController.popoverPresentationController?.sourceRect = self.photoImage.bounds
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
}
func displayPicker(type: UIImagePickerControllerSourceType) {
self.imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: type)!
self.imagePicker.sourceType = type
self.imagePicker.allowsEditing = true
DispatchQueue.main.async {
self.present(self.imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerEditedImage] as! UIImage
photoImage.contentMode = .scaleAspectFill
photoImage.image = chosenImage
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
Put this line right after imagePicker.delegate = self
imagePicker.mediaTypes = [kUTTypeImage as String]
Remember to add import MobileCoreServices at the beginning of the file.
What you want to do is after you init imagePicker set the following property
imagePicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeCamera];
https://developer.apple.com/documentation/uikit/uiimagepickercontroller/1619173-mediatypes
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()
}