Home Typing into password field in iOS app "freezes" app: iOS 11.2
Reply: 0

Typing into password field in iOS app "freezes" app: iOS 11.2

Chris Prince
1#
Chris Prince Published in 2017-12-07 22:45:57Z

In our app, when we updated to 11.2, when we type into a hidden/password field, the first character typed causes the app to "freeze". More specifically, the app stops responding-- but isn't a crash. If I run the app in Xcode, I do not get an exception and the app stays in the foreground. Literally, what I see is:

The app is frozen at this point-- you can't type any more. The keyboard stays in this state. Tapping on the screen or on "Done" doesn't do anything. It seems the only thing you can do is force-kill the app.

This is 100% reproducible. Everytime I try this, the "crash" happens.

I've tried this on several hardware devices (iPhone 6, iPhone 7 Plus, iPhone 8) all to the same effect. Each one running iOS 11.2. Same results on various simulated devices running iOS 11.2.

When running on the simulator, after getting this freeze, if I use Debug > Pause, the app does not pause. Perhaps of all of this, this is the most odd to me. Sounds like the main UI thread loop is stuck.

We've been using iOS 11.1 primarily up until this point. And a few of us have been using iOS 11.2 beta builds (though-- our app keeps your sign in info and this is only happening if you explicitly sign in).

--------- UPDATE1 -------------

To add some substance and code to this question, I put the UITextFieldDelegate below. However, if I stop using the delegate (comment out the assignment of the UITextFieldDelegate), I get a similar situation. To explain, I need to give a little more context-- As usual, there is a username along with the password field. After stopping using the delegate, if I first enter the username, and then try to enter the password-- the same thing happens. The app freezes. However, if I first enter the password and then enter the username, I can sign in to the app. With the use of the delegate, entering the password freezes the app independent of the order I enter the fields.

// MARK: UITextFieldDelegate
extension Form : UITextFieldDelegate {
    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
        if Form.forceKeyboardDismissal {
            return true
        }

        return validateField(textField, strictness: .emptyIsValid)
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        // After an error message has been displayed, and the user types into a text field, hide the text.
        if let errorMessageField = textField as? FieldErrorMessage {
            errorMessageField.hideErrorMessage()
            let parent = TextField.lookupParentFor(textField, in: textFields)!

            // I believe the text field will always be first responder here, hence it needs to be marked as selected.
            parent.show(bottomBorder: .selected)
        }

        return shouldChangeCharactersIn?(range, string, textField) ?? true
    }

    private func indexOfCurrentField(_ currentField: UITextField, in allFields: [SimpleTextField]) -> Int {
        let paddedTextFields = allFields.map({$0.basicTextField.textField})
        return paddedTextFields.index(where: {$0 == currentField })!
    }

    private func select(field: SimpleTextField?) {
        if let field = field {
            field.selectField()
        }
    }

    // In each of the following two field navigation methods, I first `resignFirstResponder`. Without this, I have an odd bug where (a) next/previous field navigation doesn't always work, and (b) Done doesn't always work-- the keyboard remains displayed (even if you leave the current screen).

    private func gotoPreviousField(currentField: UITextField) {
        currentField.resignFirstResponder()

        let allFields = forms!.flatMap({$0.textFields})
        var currIndex = indexOfCurrentField(currentField, in: allFields)
        var previousField: SimpleTextField?

        if currIndex > 0 {
            currIndex -= 1
            previousField = allFields[currIndex]
        }

        select(field: previousField)
    }

    private func gotoNextField(currentField: UITextField) {
        currentField.resignFirstResponder()

        let allFields = forms!.flatMap({$0.textFields})
        var currIndex = indexOfCurrentField(currentField, in: allFields)
        var nextField: SimpleTextField?

        if currIndex < allFields.count - 1 {
            currIndex += 1
            nextField = allFields[currIndex]
        }

        select(field: nextField)
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        if let textField = textField as? PaddedTextField {

            textField.gotoPreviousField = { currentField in
                self.gotoPreviousField(currentField: currentField)
            }

            textField.gotoNextField = { currentField in
                self.gotoNextField(currentField: currentField)
            }
        }

        hideAnyDisplayedErrorMessage()
        let parent = TextField.lookupParentFor(textField, in: textFields)!
        parent.show(bottomBorder: .selected)

        textFieldDidBeginEditing?()
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        hideAnyDisplayedErrorMessage()
        let parent = TextField.lookupParentFor(textField, in: textFields)!
        parent.show(bottomBorder: .normal)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        gotoNextField(currentField: textField)
        return false
    }
}

--------- UPDATE2 -------------

Actually, nix part of that last statement. I was operating off a different branch-- than our code branch on the app store (the one I really need to fix!). The code above still applies, but with the delegate commented out, I'm still getting the freeze issue in all cases I can determine.

One other, more interesting, new thing is that I'm now able to pause the program in the debugger and get some information. My current guess is that I have some kind of infinite layout/autolayout loop. Here is a series of three pauses of the app-- left to right increasing in time, left being earliest in the time sequence.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.63948 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO