Jivan Bhandari
Jivan Bhandari

Reputation: 860

Cannot set the UILabel Field of multiple controller

I can validate the user login in through the ViewController. Swift and redirect the view to DisplayDetailsViewController.swift which has only one UILabel named nameLabel.

Whenever there is a successful login, I am calling a function called loadValues(name: String) in DisplayDetailsViewController.swift from ViewController.swift in function login.

Whenever I try to set the value ofnameLabel, I am getting a error. If I try to set any string also the problem is same. I think I am unable to address the correct UILabel.

main.storyboard

  1. AppDegate.swift:

    //
    //  AppDelegate.swift
    //  AutoLayout
    //
    //  Created by BIKRAM BHANDARI on 11/1/17.
    //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
    //
    
    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            // Override point for customization after application launch.
            return true
        }
    
        func applicationWillResignActive(_ application: UIApplication) {
            // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
            // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        }
    
        func applicationDidEnterBackground(_ application: UIApplication) {
            // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
            // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        }
    
        func applicationWillEnterForeground(_ application: UIApplication) {
            // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
        }
    
        func applicationDidBecomeActive(_ application: UIApplication) {
            // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        }
    
        func applicationWillTerminate(_ application: UIApplication) {
            // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        }
    
    
    }
    
  2. ViewController.swift

        //
        //  ViewController.swift
        //  AutoLayout
        //
        //  Created by BIKRAM BHANDARI on 11/1/17.
        //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
        //
    
        import UIKit
    
        class ViewController: UIViewController, UITextFieldDelegate{
    
    
            @IBOutlet var txtUsername: UITextField!
            @IBOutlet var txtPassword: UITextField!
            var passWordProtected: Bool = false;
    
            var loggedInUser:User?;
    
            private struct constants{
                //static var highlighted: UIControlState{ get {return }}
            }
            //--------------------------------------------------------------------------------------------------------------------------------//
            override func viewDidLoad() {
                super.viewDidLoad();
                txtUsername.delegate = self;
    
                let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tap)); //Check the tap gesture to dissmiss the keyboard
                view.addGestureRecognizer(tapGesture)
            }
            //--------------------------------------------------------------------------------------------------------------------------------//
            @IBAction func Login() {
                if let loggedInUser = User.checkLoginCredentials(username: txtUsername.text ?? "" , password: txtPassword.text ?? ""){
    
                  let secondViewController: DisplayDetailsViewController = DisplayDetailsViewController();
                    self.present(secondViewController, animated: true, completion: nil);
                    self.performSegue(withIdentifier: "Display Details", sender: self);
    
                    txtUsername.text = "";
                    txtPassword.text = "";
    
                    let displayDetails = DisplayDetailsViewController();
                    displayDetails.loadValues(name: loggedInUser.name);
            }
        }
    func tap(gesture: UITapGestureRecognizer) { 
            txtUsername.resignFirstResponder();
            txtPassword.resignFirstResponder();
        }
    
            //--------------------------------------------------------------------------------------------------------------------------------//
            func textFieldShouldReturn(_ textField : UITextField) ->Bool{ //Function to change move to next text field when keyboard next is                            pressed
                if(textField == txtUsername){
                    txtPassword.becomeFirstResponder();
                }
                return true;
            }
    
            //--------------------------------------------------------------------------------------------------------------------------------//
            @IBAction func togglePasswordField(_ sender: UIButton) {        // Function to change the password field to secure or show the typed password
                if passWordProtected{
                    txtPassword.isSecureTextEntry = true;
                    sender.setImage(#imageLiteral(resourceName: "view"), for: UIControlState.normal)
                    passWordProtected = false;
    
                }else{
                    txtPassword.isSecureTextEntry = false;
                    sender.setImage(#imageLiteral(resourceName: "hide"), for: UIControlState.normal)
                    passWordProtected = true;
                }
            }
    
        }
    
  3. User.swift

    //
    //  User.swift
    //  AutoLayout
    //
    //  Created by BIKRAM BHANDARI on 15/1/17.
    //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
    //
    
    import Foundation
    struct User{
        let name: String;
        let company: String;
        let username: String;
        let password: String;
    
        static func checkLoginCredentials(username: String, password: String) -> User?{
            if let user = database[username]{
                if user.password == password{
                    return user;
                }
            }
            return nil;
        }
    
        static let database: Dictionary<String, User> = {
        var theDatabase = Dictionary<String, User>()
        for user in [
            User(name:"Bikram", company:"Self Company", username:"bikram", password:"bhandari"),
            User(name:"Sabina", company:"No company till now", username:"Sabina", password:"Sabu"),
            User(name:"Mac", company:"Apple Inc. ", username:"iphone", password:"6plus"),
            User(name:"Samsunng", company:"Sumsung Inc.", username:"note", password:"7")
            ]{
                theDatabase[user.username] = user;
            }
            return theDatabase
        }();
    }
    
  4. DisplayDetailsViewController.swift

    //  DisplayDetailsViewController.swift
    //  AutoLayout
    //
    //  Created by BIKRAM BHANDARI on 15/1/17.
    //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
    //
    import UIKit
    
    class DisplayDetailsViewController: UIViewController {
    
        @IBOutlet weak var nameLabel: UILabel!
    
        //***********************************//
        func loadValues(name: String){
            nameLabel.text = "Bikram";
        }
    
    }
    
  5. updated ViewController.swift

    //
    //  ViewController.swift
    //  AutoLayout
    //
    //  Created by BIKRAM BHANDARI on 11/1/17.
    //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
    //
    
    import UIKit
    
    class ViewController: UIViewController, UITextFieldDelegate{
    
    
        @IBOutlet var txtUsername: UITextField!
        @IBOutlet var txtPassword: UITextField!
        var passWordProtected: Bool = false;
    
        var loggedInUser:User?;
    
        private struct constants{
            //static var highlighted: UIControlState{ get {return }}
        }
        //--------------------------------------------------------------------------------------------------------------------------------//
        override func viewDidLoad() {
            super.viewDidLoad();
            txtUsername.delegate = self;
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tap)); //Check the tap gesture to dissmiss the keyboard
            view.addGestureRecognizer(tapGesture)
        }
        //--------------------------------------------------------------------------------------------------------------------------------//
        @IBAction func Login() {
            if let loggedInUser = User.checkLoginCredentials(username: txtUsername.text ?? "" , password: txtPassword.text ?? ""){
    
              let secondViewController: DisplayDetailsViewController = DisplayDetailsViewController();
                self.present(secondViewController, animated: true, completion: nil);
                self.performSegue(withIdentifier: "Display Details", sender: self);
    
                txtUsername.text = "";
                txtPassword.text = "";
    
                let displayDetails = DisplayDetailsViewController();
                displayDetails.user = loggedInUser;
        }
    }
        //--------------------------------------------------------------------------------------------------------------------------------//
        func tap(gesture: UITapGestureRecognizer) { //Function to dismiss the keyboard when it is pressed anywhere in the storyboard.
            txtUsername.resignFirstResponder();
            txtPassword.resignFirstResponder();
        }
    
        //--------------------------------------------------------------------------------------------------------------------------------//
        func textFieldShouldReturn(_ textField : UITextField) ->Bool{ //Function to change move to next text field when keyboard next is                            pressed
            if(textField == txtUsername){
                txtPassword.becomeFirstResponder();
            }
            return true;
        }
    
        //--------------------------------------------------------------------------------------------------------------------------------//
        @IBAction func togglePasswordField(_ sender: UIButton) {        // Function to change the password field to secure or show the typed password
            if passWordProtected{
                txtPassword.isSecureTextEntry = true;
                sender.setImage(#imageLiteral(resourceName: "view"), for: UIControlState.normal)
                passWordProtected = false;
    
            }else{
                txtPassword.isSecureTextEntry = false;
                sender.setImage(#imageLiteral(resourceName: "hide"), for: UIControlState.normal)
                passWordProtected = true;
            }
        }
    
    }
    
  6. Updated DisplayDetailsViewController

    //
    //  DisplayDetailsViewController.swift
    //  AutoLayout
    //
    //  Created by BIKRAM BHANDARI on 15/1/17.
    //  Copyright © 2017 BIKRAM BHANDARI. All rights reserved.
    //
    
    import UIKit
    
    class DisplayDetailsViewController: UIViewController {
    
        @IBOutlet weak var nameLabel: UILabel!
    
        var user: User!{
            didSet{
            nameLabel.text = user.name}
        }
        //***********************************//
    }
    

Upvotes: 0

Views: 62

Answers (1)

Shawn Frank
Shawn Frank

Reputation: 5143

nameLabel has probably not been initialised as yet as it is not yet on screen.

try creating a var in DisplayDetailsViewController that holds the user object.

Instead of:

displayDetails.loadValues(name: loggedInUser.name);

Try:

displayDetails.user = loggedInUser; 
// assuming you have created a var in DisplayDetailsViewController
// called user of type User

Then in the viewWillAppear of DisplayDetailsViewController, add your original line of code:

nameLabel.text = user.name

Does this work ?

EDIT

I have this as my struct

struct User
{
    var name = ""
    var age = 0
}

Before transitioning to the next screen (either before push view controller or in prepare for segue), you need to instantiate your user, for example I am doing this in:

override func prepare(for segue: UIStoryboardSegue, sender: Any?)

let user = User(name: "Shawn", age: 26)        
let destination =  segue.destination as! DisplayDetailsViewController
destination.user = user

Then finally, the DisplayDetailsViewController:

class DisplayDetailsViewController: UIViewController {

    var user = User()

    @IBOutlet var label: UILabel!

    override func viewWillAppear(_ animated: Bool) {
        label.text = user.name
    }
} 

I run this and I get the label sucessfully showing Shawn on the detail screen

Upvotes: 1

Related Questions