skip to Main Content

Executing the following lines in your app will somehow break the keyboard and its toolbar. The toolbar "detaches" from the keyboard and starts sliding in and out at the very top of the screen underneath the status bar.

if #available(iOS 13.0, *) {
    for scene in UIApplication.shared.connectedScenes {
        guard let windowScene = scene as? UIWindowScene else { continue }
        for window in windowScene.windows {
            for view in window.subviews {
                view.removeFromSuperview()
                window.addSubview(view)
            }
        }
    }
} else {
    for window in UIApplication.shared.windows {
        for view in window.subviews {
            view.removeFromSuperview()
            window.addSubview(view)
        }
    }
}    

I know that this is very "hacky", I just stumbled upon it and now I am curious on why removing and adding the views causes this behavior. Does anyone have an idea? (It also happens with toolbars that were added by the system, e.g. in a webview)

Hard to see here but you can see the left toolbar button:
enter image description here

2

Answers


  1. The removeFromSuperView() method will remove all auto layout constraints that refer to the view being removed, as well as the sub-views of that view. They aren’t going to magically come back into existence just because you re-add the view, so you’ll end up with whatever the view’s frame happens to be.

    Since you’re experimenting here though, you could try this to see if the views restore their constraints:

            for view in window.subviews {
                let constr = view.constraints
                view.removeFromSuperview()
                window.addSubview(view)
                NSLayoutConstraint.activate(constr)
            }
    
    Login or Signup to reply.
  2. The problem is that there are always multiple windows, one of which is the UITextEffectsWindow, which is responsible for displaying the keyboard (and possibly other views, since it’s a private API, there aren’t any official documentations for it).

    Ignoring the UITextEffectsWindow while traversing your windows will fix your keyboard problem.

    for window in windowScene.windows.reversed() {
        if NSStringFromClass(window.classForCoder) == "UITextEffectsWindow" {
            NSLog("===== Ignore UITextEffectsWindow")
    
            return
        }
    
        for view in window.subviews.reversed() {
            view.removeFromSuperview()
            window.addSubview(view)
        }
    }
    

    But since UITextEffectsWindow is a private API, maybe you should do the reverse and only remove views, if the window is a UIWindow.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search