Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UiTextField changes font while editing in Swift 1.2 & 2.0

Tags:

ios

uikit

I have a UITextField with a custom font, everything worked fine until Swift update to 1.2 and 2.0. Afterwards, each time I try to edit a text field, it changes its font to a different one that seems a sort of Times New Roman. Does anyone have experience of that?

like image 562
matCode Avatar asked Feb 11 '15 12:02

matCode


4 Answers

I came across this same issue and figured out a solution. The problem boils down to setSecureTextEntry changing the font when it is set, and not changing it back when it is unset. In fact, you can never change the font back as long as your UITextField has first responder.

The trick is to resignFirstResponder before you call setSecureTextEntry: and then becomeFirstResponder again. This will work (as of iOS 9.2), but it triggers the keyboard show/hide animation and will cause the screen to "shake". To get around that, you'll need to kill the keyboard animation as well.

Here's my full solution:

- (void)setSecureTextEntry:(BOOL)secureTextEntry {

    __weak typeof(self) weakSelf = self;
    [UIView performWithoutAnimation:^{

        BOOL resumeResponder = NO;
        if([[weakSelf textEntryField] isFirstResponder]) {
            resumeResponder = YES;
            [[weakSelf textEntryField] resignFirstResponder];
        }

        [[weakSelf textEntryField] setSecureTextEntry:secureTextEntry];

        if(resumeResponder) {
            [[weakSelf textEntryField] becomeFirstResponder];
        }
    }];
}

PS: This isn't a Swift bug. It's a UIKit bug. I had the same issue with Objective-C.

like image 78
Alexander Avatar answered Nov 15 '22 20:11

Alexander


I had a weird case of fonts changing its size and font type, when secureTextEntry for an UiTextField was toggled by using a button action. enter image description here Had to explicitly manage font for the UiTextField by using these lines of code:

password.font = UIFont(name: "systemFont", size: 14)
password.font = UIFont.systemFontOfSize(14)

Complete Code used in the Show Password Button:

//Function associated with the button for show password option
@IBAction func switchShowPasswordAction(sender: AnyObject) {
        if showPassword{
            showPassword  = false
            password.secureTextEntry = !showPassword

        }else{
            showPassword = true
            password.secureTextEntry = !showPassword
        }

        //Changing font fix
        password.font = UIFont(name: "systemFont", size: 14)
        password.font = UIFont.systemFontOfSize(14)
}

Post applying this change: enter image description here

like image 44
Abhijeet Avatar answered Nov 15 '22 19:11

Abhijeet


Since I used custom fonts we need to preserve the original font. Create an extension to UITextField:

extension UITextField {
    func enablePasswordModeWithShowHide() {
        secureTextEntry = false
        let showButton = UIButton(type: UIButtonType.System)
        showButton.setTitle("HIDE", forState: .Normal)
        showButton.titleLabel?.textAlignment = .Right
        showButton.sizeToFit()
        rightView = showButton
        rightViewMode = .Always
        showButton.addTarget(self, action: "handleShowHideTapped", forControlEvents: .TouchUpInside)
        showButton.tintColor = UIColor.blackColor()
    }

    func handleShowHideTapped() {
        secureTextEntry = !secureTextEntry
        let font = self.font
        self.font = nil
        self.font = font
        if let oldText = text {
            text = "";
            text = oldText;
        }

        if let button = rightView as? UIButton {
            button.setTitle(secureTextEntry ? "SHOW" : "HIDE", forState: .Normal)
            button.sizeToFit()
        }
    }
}

Where it could be implemented like this:

passwordTextField.enablePasswordModeWithShowHide()
like image 25
Daniel Galasko Avatar answered Nov 15 '22 18:11

Daniel Galasko


All of these answers pretty much work, but I had to use a different solution to achieve the results I needed, considering I'm using a custom font.

You need to make the text field attributed in the storyboard inspector pane for the UITextField, as follows:

attributed selected in inspector

Then, in code, you need to manage the toggling of the visibility, setting the attributed text each time, to ensure its properly formatted. I also resignFirstResponder() on the field just to take care of some positioning glitch that I still haven't figured out yet.

func toggleShowPass() {
    self.showing = !showing

    txtpassword.secureTextEntry = !showing
    textFieldPassword.resignFirstResponder()

    let string = textFieldPassword.text!
    let attrString = NSMutableAttributedString(string: string)

    textFieldPassword.addAttribute(NSFontAttributeName, value: UIFont(name: "AvenirNext-Regular", size: 16.0)!, range: NSMakeRange(0, string.characters.count))
    textFieldPassword.attributedText = attrString

}
like image 31
tyler Avatar answered Nov 15 '22 19:11

tyler