How to pass Firebase UID using prepare for segue - ios

I am using Swift and Firebase and I am trying to pass the UID in a prepare for segue. So when the user logs in and does something on the next view it will know it is him/her. However, when I do this I keep getting nil
This is the code that I have tried.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "fromNewUserToAddCard" {
if let destination = segue.destination as? AddCardViewController {
destination.uid = tempUID
}
}
}
I have a property on the AddCardViewController of uid that tempUID is supposed to transfer to.
How can I fix this?
Thanks

Why don't you simply ask for FIRAuth.auth()?.currentUser?.uid each time you want the user's uid? This is easier than handling the uid storage yourself

Related

Passing error with "perform segue" returns nil?

I am trying to show app users the error when they login in or register in a wrong way, for example the password needs 6 characters so if he/she entered 4 or 5 its should bring him error but it only prints in Xcode and always nil in the app (I am new here and the website tells me the picture size is too big to be uploaded so ill write down). Can someone help me figure what's wrong with the code here ? Thanks!!
// This is the code for the first viewcontroller where I try to pass the error to the ErrorViewController
if let email = emailTextfield.text, let password = passwordTextfield.text{
Auth.auth().signIn(withEmail: email, password: password) { [weak self] authResult, error in
if let e = error {
print(e)
self!.performSegue(withIdentifier: "GoToError", sender: self)
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "GoToError" {
let GoTo = segue.destination as! ErrorViewController
GoTo.errorText = "\(e.localizedDescription)"}
}
}else{
self!.performSegue(withIdentifier:K.loginSegue, sender: self)
}
}
}
// This is the code of the ErrorViewController where It should catch the error and pass it to the ErrorText label and get printed to the app screen
errorText: String?
#IBOutlet weak var ViewMessage: UIView!
#IBOutlet weak var ErrorText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
ViewMessage.layer.cornerRadius = ViewMessage.frame.size.height / 4
if errorText != nil {
ErrorText.text = errorText
}else{
// The string below is what gets printed because the error is always nil
ErrorText.text = "make sure your password is at least 6 characters"
The reason is that prepare(for segue must be implemented on the top level of the class (same level as viewDidLoad).
And please name variables, functions and enum cases with starting lowercase letter.
func prepare(for segue: UIStoryboardSegue, sender: Any?)
This function is called every time segue occurs (when performSegue(withIndentifier:sender) function calls).
viewController has no access to prepare() function because it is in local scope of if/else block.
More specifically, prepare(for segue) function exists only in scope of if/else block, that is wrapped in a closure, that is wrapped in another if/else block.
But this function should be always accessible for viewController, that why it should be placed in a top level scope.
Like that
class MyViewController: UIViewController {
//other class properties and methods
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//your code here
}
}
I would suggest to read more about scope & context in swift.

transfer weather data to container view

Im unable to update labels in container view. Here's how i've done it.
​
I wrote my updateWeather function in main VC and retrieved the weather data successfully. when i printed weatherJSON it shows all the received data in console.
now when i started writing updateUI function i could only update the labels on main VC.
so i used prepare segue to send data to container view and sent a string to container VC and updated "humidity" label successfully. all labels accept strings without any issues.
but i have no idea how to send weather data to container view.
i tried passing values using object weatherDataModel but nothing happens. i even declared a new object referring to container view class and used it in updateUI function to set label values but it won't work too.
I have no idea what to pass in place of string to get weather data through to next VC.
override func prepare(for segue: UIStoryboardSegue, sender for: Any?) {
if segue.identifier == "displayFullWeatherInfo"{
let destinationVC = segue.destination as! FullWeatherViewController
destinationVC.delegate = "\(weatherDataModel.pressure)"
....
....
Heres my WeatherDataModel Class:
import Foundation
class WeatherDataModel{
var city = ""
var temp = 0
var country = ""
var humidity = 0
}
in my main VC i have created weatherDataModel object and here's my updateWeatherInfo code:
func updateWeatherInfo(json : JSON){
if let tempDefault = json["data"][0]["temp"].double{
weatherDataModel.temp = Int(tempDefault)
weatherDataModel.city = json["data"][0["city_name"].stringValue
weatherDataModel.country = json["data"][0]["country_code"].stringValue
weatherDataModel.humidity = json["data"][0]["rh"].intValue
updateWeatherUI()
}
else{
currentLocation.text = "Not Available"
}
}
​
Create a property for your weather model object in your second VC FullWeatherViewController:
var weatherDataModel: WeatherDataModel! //your object
And in your first VC:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "displayFullWeatherInfo" {
let destinationVC = segue.destination as! FullWeatherViewController
destinationVC.weatherDataModel = weatherDataModel
}

Swift: Need to move data stored using a button to another View Controller

Using a button to collect a phone number and then reading and storing the phone number under the button function.
#IBAction func viewRewardsButtonTapped(_ sender: UIButton) {
view.endEditing(true)
// Validate format
let phoneNumberInput = phoneInput.text
}
Is there a better way to store the phone number phoneNumberInput and get it to another UIViewController?
I currently can't get the other UIViewController to recognize the variables stored under the #IBAction function.
You could use UserDefaults:
// Set phone number
UserDefaults.standard.set(phoneInput,text, forKey: "phoneNumber")
// Get phone number
UserDefaults.standard.string(forKey: "phoneNumber")
Or if you want to segue at the same time that you´re clicking the button use this:
self.performSegue(withIdentifier: "showVC2", sender: phoneNumber.text)
override func prepare(for segue: UIStoryboardSegue, sender: Any!) {
if (segue.identifier == "showVC2") {
if let phoneNumber = sender as? String {
let vc = segue.destination as! YourSecondVC
vc.phoneNumber = phoneNumber
}
}
}
So you basically create the segue and declare a variable for phoneNumber in your second VC so that you can pass the value to it.
Your phoneNumberInput variable is only stored in the scope of your action handler method viewRewardsButtonTapped, so once this method is left the value is lost. You should add a member variable (var phoneNumber: String?) to your class and use this for storing the value. Then, when you open the next view controller, you can pass the value in as a parameter.
If you are using storyboard segues (which I assume), you have to implement performSegue withIdentifier, cast the destination view controller to the concrete type and set the value (e.g. targetVC.phoneNumber = self.phoneNumber).

Assign strings to textfields in another view controller

I am trying to take facebook values, such as name and email, and transferring them to another view controller where they populate their corresponding text fields. However, when I try to populate the text fields with this code
let fbEmail = data["email"]
let fbName = data["name"]
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? CreateAccountVC
vc!.emailTxt = self.fbName
vc!.fullnameTxt = self.fbEmail
}
I receive an error saying "Cannot assign type String to type UITextField!" I'm confused here as I thought that text fields only take strings (I'm very new to coding/programming).
So basically, how do I get these values gathered in one view controller to populate text fields in another view controller? Any help would be greatly appreciated! Thanks!
Error reason is you need to assign it to the UITextField's text property.
You can also use variables to set them. And set textfield's values in your CreateAccountVC controller's viewDidLoad function. Like this:
Your first controller where you take facebook values:
let fbEmail = data["email"]
let fbName = data["name"]
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? CreateAccountVC {
vc.emailTxtValue = self.fbName
vc.fullnameTxtValue = self.fbEmail
}
}
Your CreateAccountVC :
class CreateAccountVC: UIViewController {
var emailTxtValue:String?
var fullnameTxtValue:String?
override func viewDidLoad() {
super.viewDidLoad()
emailTxt.text = emailTxtValue
fullnameTxt.text = fullnameTxtValue
}
}

Playing recorded audio with swift

I am currently working through the "Intro to iOS App Development with Swift" course through Udacity. I have copied the code exactly up to the point where we finish recording the audio. This is what they tell you to type:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if (segue.identifier == "stopRecording"){
let playVC:PlayViewController = segue.destinationViewController as PlayViewController
let data = sender as RecordedAudio
playVC.receivedAudio = data } }
However, it returns a compiler error and asks me to add the exclamation point after both as. When I run the program, it says "I found nil while unwrapping an optional". I'm relatively new to programming, so any advice would be helpful.
I just completed this course. So basicly what you are tring to do is passing data between differnet screens. Try to understand what are you tring to achive and it help you to understand the code better.
The main task for the first screen is to record audio, after the task completed, you store all the information about the completed task into an object called RecordedAudio. The information included are var title: String! and var filePathURL: NSURL!. After we store the recording info., we are ready to pass it to the next screen's controller, namely PlayScreenController. First, we have to get access to the conroller and than passing the data.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
// Checking segue if there are more than one
if (segue.identifier == "stopRecording") {
// Get the PlayScreenController access
let playSoundVC = segue.destinationViewController
as playScreenViewController
// Cast sender into a RecordedAudio Object
let data = sender as RecordedAudio
// Passing the data to PlayScreen
playSoundVC.audioData = data
}
}
Now everything is prepared, we can perform the segue. During perform the segue we have to provide the identity of segue and who are the sender.
var recordedAduio = RecordedAduio()
recordedAduio.filePathURL = recorder.url
recordedAudio.title = recorder.url.lastPathComponent
self.performSegueWithIdentifier("stopRecording", sender: recordedAudio)
Pay attention to the sender object in performSegueWithIdentifier that the reason why we can cast the send in prepareSegue into a RecordedAudio object.
NOTE: Remeber to define var audioData: RecordedAudio! in the PlayScreenViewController otherwise you cannot pass the data to the second screen, becuase there is no variable can hold the data which you are trying to pass.

Resources