Search code examples
iosnullswift2iboutlet

IBOutlet always nil in ViewController methods but ok in IBAction & Viewdidload


I try to access some IBOutlet outside of Viewdidload and IBAction, and always get nil value. In Viewdidload and IBAction, those value are ok. Did i miss a part to declare or initialize something ?

The value are modified after viewdidload() because viewdidload is called bu the IBAction.

The View is created in storyboard, coming from a UINavigation Controller.

connection table between ViewController and UIView:

The loginServer method is called by userCredential delegate, as below:

protocol userCredentialDelegate {
    func didUpdateCredential (sender:String, credential: Bool?)
}

class userCredential: NSObject {

var delegate:userCredentialDelegate?
// self.delegate = ViewController() removed

func loginServer (name: String, pwd: String) -> Bool {
dispatch_sync(dispatch_get_main_queue())
     {
     self.delegate?.didUpdateCredential ("login", credential: credentialStatus)
     }
}

Main controller:

class ViewController: UIViewController, userCredentialDelegate  {

// set the shared instance
let user = userCredential.sharedInstance

@IBOutlet weak var incorrectCredentials: UITextField!
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var logButton: UIButton!

@IBAction func logButton(sender: UIButton) {
    print (incorrectCredentials?.hidden)
    if logButton.titleLabel!.text == "Log Out" {
        user.logoutServer ()
    } else {
        user.loginServer(username.text!, pwd: password.text!)
    }
}

func didUpdateCredential (sender: String, credential: Bool?) {
    switch sender {
    case "login":
        if credential! {
            performSegueWithIdentifier("loginSegue", sender: self)
        } else {
            incorrectCredentials?.hidden = false
        }
    default: break
    }
    if let credentialResponse = credential {
        loginStatus = credentialResponse
        }
    }

var loginStatus: Bool = false {
    didSet {
        if loginStatus {
            incorrectCredentials?.hidden = true                    // always nil before, now ok
        } else {
            incorrectCredentials?.hidden = false                   // always nil before, now ok
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    user.delegate = self
    incorrectCredentials.hidden = true  // can work here
    user.getUserInfo ()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

connection table:


Solution

  • You need to set the delegate to your user model in your viewDidLoad function. Before doing user.getUserInfo() make user.delegate = self

    currently you create a new Instance on the user model, that has nothing todo with you real loaded ViewController.