Aashish Nagar
Aashish Nagar

Reputation: 1227

UITextField delegate method not called

I am presenting an alert with UITextfield, but its delegate methods are not getting called. What wrong I might be doing. I am using the below code to show the alert with textfield.

  func takePasscodeToEnableTouch(){
   self.passcodeInputOperationType = .EnableTouchID

   alertControllerPassCodeEntry = UIAlertController(title: "", message: "Enter Passcode to enable the Touch Id.", preferredStyle: UIAlertControllerStyle.Alert)

    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (action) -> Void in
    }
    alertControllerPassCodeEntry!.addAction(cancelAction)

    alertControllerPassCodeEntry!.addTextFieldWithConfigurationHandler { (txtField) -> Void in
        txtField.placeholder = "Enter passcode"
        txtField.delegate = self
        txtField.tag = TextFieldTag.EnterPassCode
        txtField.keyboardType = UIKeyboardType.NumbersAndPunctuation
        txtField.accessibilityIdentifier = "PassCode"
        txtField.secureTextEntry = true
        txtField.addTarget(self, action:"textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
    }

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    appDelegate.window?.rootViewController?.presentViewController(alertControllerPassCodeEntry!, animated: true, completion: nil )
}

And the textField delegate methods are :

func textFieldShouldBeginEditing(textField: UITextField) -> Bool
{
    return true
}

func textFieldDidBeginEditing(textField: UITextField) // became first responder
{

}

func textFieldShouldEndEditing(textField: UITextField) -> Bool
{
    return true
}

func textFieldDidEndEditing(textField: UITextField)
{

}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    var isLimitExist: Bool
    var accessIndentifier: String
    if let str = textField.accessibilityIdentifier
    {
        accessIndentifier = str
    }
    else
    {
        accessIndentifier = ""
    }

    //checkFieldLimit function is used to check the limit of text and restrict
    isLimitExist = UIUtils.checkFieldLimit(accessIndentifier, stringToMatch: textField.text!, rangeLength: range.length, stringLength: string.characters.count)

    if !isLimitExist
    {
        return false
    }
    return true
}

Upvotes: 0

Views: 755

Answers (1)

Losiowaty
Losiowaty

Reputation: 8006

Ok, so with information from the comments, everything seems clear now. To recap, you call the method showing the alert like this :

@IBAction func swtchTouchAction(sender: UISwitch) { 
    if sender.on { 
        let passCodeManager = PasscodeManager() 
        passCodeManager.delegate = self 
        passCodeManager.takePasscodeToEnableTouch() 
    } else { 
        let passCodeManager = PasscodeManager() 
        passCodeManager.delegate = self
        passCodeManager.authenticatePasscodeToDisalbeTouch() 
    } 
}

Now, you don't retain (meaning - assign to a strong property) the passCodeManager anywhere in here. This means, that at the end of this method this object gets destroyed (thanks to ARC - Automatic Reference Counting). One may think that it would get retained because you assigned it as a delegate of the text field, but delegates are weak proeprties 99.99% of time - this means that they don't bump the retain count of objects assigned to them.

To solve your immediate issue you should make a property in your class in which you have swtchTouchAction method and change your code like this :

var passCodeManager: PasscodeManager?

@IBAction func swtchTouchAction(sender: UISwitch) { 
    if sender.on { 
        self.passCodeManager = PasscodeManager() 
        self.passCodeManager?.delegate = self 
        self.passCodeManager?.takePasscodeToEnableTouch() 
    } else { 
        self.passCodeManager = PasscodeManager() 
        self.passCodeManager?.delegate = self
        self.passCodeManager?.authenticatePasscodeToDisalbeTouch() 
    } 
}

This will be enough to retain your passcode manager.

I'd also suggest you read up on how memory management is done in Swift.

Upvotes: 1

Related Questions