Button.titleLabel error in swift3 - ios

I am trying to compare the title that I have in a button so that if it is compared to another it does a certain thing or not. I'm using the .setTitle function but I think in swift3 it gives error and I can not find the why. Then I leave a catch of the error to make it easier to see it and also the code itself. Thanks for the help
#IBAction func _login_button(_ sender: Any)
{
if(_login_button.titleLabel?.text == "OKEY")
{
let preferences = UserDefaults.standard
preferences.removeObject(forKey: "session")
LoginToDo()
return
}
let username = _username.text
let password = _password.text
if(username == "" || password == "")
{
return
}
DoLogin(username!, password!)
}

change your #IBAction func _login_button(_ sender: Any) to you need to type cast from Any to UIButton #IBAction func _login_button(_ sender: UIButton)
#IBAction func _login_button(_ sender: UIButton)
{
if(sender.titleLabel?.text == "OKEY")
{
}
}

_login_button is #IBAction you have to create the button for #IBOutlet of button

you need to get button as below , now you access function name instead of sender
#IBAction func _login_button(_ sender: Any)
let button: UIButton = sender as! UIButton
if(button.titleLabel?.text == "OKEY")
{
}
}

If you get this error as per screen shot, you need to type cast from Any to UIButton and then use titleLabel property.

Related

Swift UIBarButtonItem Title

#IBAction
func buttonTapped(_ sender: UIBarButtonItem) {
guard let title = sender.currentTitle,
let button = Buttons(rawValue: title) else { return }
}
The error I am getting says “Value of type ‘UIBarButtonItem’ has no member ‘currentTitle’, I have enums and cases for each button too.
Try gaurd let title = sender.title

Swift - Execute performSegue under conditions

My intention is to run performSegue solely if all textfields are filled. If not, the button is not supposed to work - to be exact, performSegue shall not be executed.
My approach was to put performSegue inside of an if statement, but somehow it's being ignored and performSegue is being executed anyways, even though both fields are empty. Is there another more successful approach?
#IBAction func buttonAdd(_ sender: Any) {
if (addKmInput.text! != "" && addPriceInput.text != "") {
...
performSegue(withIdentifier: "goBackToSecond", sender: self)
}
}
#IBOutlet weak var addKmInput: UITextField!
#IBOutlet weak var addPriceInput: UITextField!
New version:
#IBAction func buttonAdd(_ sender: Any) {
performSegue(withIdentifier: "goBackToSecond", sender: self)
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
switch identifier {
case "goBackToSecond":
return shouldGoBackToSecond()
default:
return true
}
}
func shouldGoBackToSecond() -> Bool {
guard let kmInput = addKmInput.text, let priceInput = addPriceInput.text else { return false }
return !kmInput.isEmpty && !priceInput.isEmpty
}
Try following solution:
#IBAction func buttonAdd(_ sender: Any) {
if shouldGoBackToSecond() {
performSegue(withIdentifier: "goBackToSecond", sender: self)
}
}
func shouldGoBackToSecond() -> Bool {
guard let kmInput = addKmInput.text, let priceInput = addPriceInput.text else { return false }
return !kmInput.isEmpty && !priceInput.isEmpty
}
use str.isEmpty to check if the string int he textField is empty :
if let t1 = addKmInput?.text, let t2 = addPriceInput?.text, !t1.isEmpty, !t2.isEmpty {
...
performSegue(withIdentifier: "goBackToSecond", sender: self)
}
and you should ideally use this delegate to deny segue performance:
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return true //return true/false conditionally. returning false will prevent segue performance.
}

How can I call in Swift 3 the method prepare after the user's input has four characters?

I have the following methods:
#IBAction func postcodeTextfieldDidChanged(_ sender: UITextField) {
if (postcodeTextField.text?.characters.count == 4) {
self.postcode = postcodeTextField.text
postcodeHas4Chars = true
} else {
postcodeHas4Chars = false
}
}
And the prepare-method:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "CoffeeShopListWithPostcode" {
if (postcodeHas4Chars == true) {
if let list = segue.destination as? CoffeeShopListVC {
list.postcode = postcode
} else {
print("Data NOT Passed!")
}
}
} else { print("Id doesnt match with Storyboard segue Id")
}
}
The code works and I can send the postcode to the next ViewController, but how can I change the code to automatically call the method after the fourth input?
At the moment, the user must manually exit the input so that it can be executed.
Each time the text field's text change, check if the text is 4 characters. If it is, call performSegue(withIdentifier, sender:). Simple:
#IBAction func postcodeTextfieldDidChanged(_ sender: UITextField) {
if (postcodeTextField.text?.characters.count == 4) {
self.postcode = postcodeTextField.text
postcodeHas4Chars = true
performSegue(withIdentifier: "CoffeeShopListWithPostcode", sender: self)
} else {
postcodeHas4Chars = false
}
}
Also, remember that you connect to the editingChanged event instead of the valueChanged event.

Perform some code before a segue after I push a button in swift

I have a button that goes to another view. I want to perform some code before the segue moves. The problem I am facing is the segue goes to the other page before the code has a chance to finish. So the values that are in the User default don't get changed before the view gets changed.
My question is how can I get the code to run and after its done get the segue to fire?
Here is what I have so far:
#IBAction func onLogoutClick(sender: AnyObject) {
//clear all url chache
NSURLCache.sharedURLCache().removeAllCachedResponses()
//null out everything for logout
email = ""
password = ""
self.loginInformation.setObject(self.email, forKey: "email")
self.loginInformation.setObject(self.password, forKey: "password")
self.loginInformation.synchronize()
//self.view = LoginView
}
You have a couple of options;
The first is to remove the action from the button in IB and then create a segue between the UIViewController object and your next scene;
#IBAction func onLogoutClick(sender: AnyObject) {
//clear all url chache
NSURLCache.sharedURLCache().removeAllCachedResponses()
//null out everything for logout
email = ""
password = ""
self.loginInformation.setObject(self.email, forKey: "email")
self.loginInformation.setObject(self.password, forKey: "password")
self.loginInformation.synchronize()
self.performSegueWithIdentifier("logoutSegue",sender: self)
}
or you can get rid of the #IBAction method and implement prepareForSegueWithIdentifier
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "logoutSegue" {
//clear all url chache
NSURLCache.sharedURLCache().removeAllCachedResponses()
//null out everything for logout
email = ""
password = ""
self.loginInformation.setObject(self.email, forKey: "email")
self.loginInformation.setObject(self.password, forKey: "password")
self.loginInformation.synchronize()
}
}
In your view controller you can implement:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "Segue identifier set in storyboard") {
// Put your code here or call onLogoutClick(null)
}
}
For Swift 4:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "Segue identifier set in storyboard") {
// Put your code here
}
}

Finding nil when prepareForSegue Swift

I am not at all sure why this is happening. When I try to use prefpareForSegue I get "Unexpectedly found nil while unwrapping optional values". I know what it means and where it is happening but I have no clue why.
There error happens on either of the lines marked in my code. I have already tested the values dateText and currentDate and neither are nil.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var DestViewController : CreatePostScrollViewController = segue.destinationViewController as! CreatePostScrollViewController
if dateText != "" {
DestViewController.startTimeDateButton.setTitle(dateText, forState: .Normal)// Error Here
} else if dateText == "" {
DestViewController.startTimeDateButton.setTitle(currentDate, forState: .Normal)// Error Here
}
}
Any help is much appreciated!
When prepareForSegue is called, the user interface elements of the destination controller might not yet be initialized. What you should instead do, is have a field in CreatePostScrollViewController like this:
var buttonTitle: String?;
Then in your viewWillAppearMethod within CreatePostScrollViewController set the button's title to the buttonTitle field you have like this:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
if let buttonTitle = buttonTitle {
startTimeDateButton.setTitle(buttonTitle, forState: .Normal);
}
}
Finally to finish the tale in the prepareForSegue do:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var DestViewController : CreatePostScrollViewController = segue.destinationViewController as! CreatePostScrollViewController
if dateText != "" {
DestViewController.buttonTitle = dateText
} else if dateText == "" {
DestViewController.buttonTitle = currentDate
}
}

Resources