Search code examples
iosswiftmacosuitextfieldmac-catalyst

Strange Transparent View Appears Beneath Textfield in Mac Catalyst App


I'm in the process of creating a Mac Catalyst app from my existing iOS app. My problem is this strange transparent view that appears beneath my secure textfields. It appears when the textfield gets the focus by clicking into it, entering one or more characters and deleting every character in the textfield. This does not happen on iOS. The app is all UIKit and Swift no SwiftUI involved.

A character in a secure textfield in a catalyst appIn the first image you can see there's a character in the textfield.

Deleted the character, a transparent view appearsThe second I delete it, this strange view appears. I can not remove this view by clicking somewhere else within the app's window. I can remove it, however, by switching to another app or by hitting the escape key.

Another example of the transparent viewIn the third image you can see another instance of this transparent view/panel/window on a white background where it can be seen more clearly.

Unfortunately, it's not possible to capture it in Xcode's "Dubug View Hierarchy" since the view is gone the second the app goes to the background.

User rene seems to have the exact same problem but he's using SwiftUI which I don't.

I read through posts regarding similar issues and they seem to be solved by telling the secure UITextField that its "textContentType" is ".oneTimeCode" or anything else except ".password" but that idea didn't help me with my problem. I tried setting the "textContentType" and I tried setting the "keyboardType" as well. Both approaches failed solving my problem.

I have the impression that the OS is trying to present me the "passwords" feature so that I don't have to type in a password but this is only a theory since I don't see the grayish view saying "Passwords".

User Eddie Ed mentions a similar problem but hasn't gotten any answers yet.

Maybe it's simply a bug with Catalyst, I don't know. I haven't filed a radar yet. Hopefully, you helpful people have an idea or encountered and solved this problem one way or another. Any help is appreciated. Thank you.


Solution

  • I came up with this workaround:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let backspaceWasPressed = string == ""
        let entireTextSelected = range.length == textField.text?.count
    
        if backspaceWasPressed && (textField.text?.count == 1 || entireTextSelected) {
            textField.text = ""
            return false
        }
    
        return true
    }
    

    It looks like preventing a default behavior here helps.

    EDIT: Updated code that checks if the entire text was selected as suggested by @HagnarRash.

    EDIT2: I have two more observations. The bug doesn't seem to occur at all if touch ID is used initially in the app. Another observation is that

    textField.isSecureTextEntry = false
    textField.isSecureTextEntry = true
    

    seems to help even in the cases where Touch ID is not used(, but I have no idea what happens under the hood that could explain why it helps).