Keyboard/Toolbar 在 window 中删除和添加视图时中断

Keyboard/Toolbar breaks when removing and adding views in window

在您的应用中执行以下行会以某种方式破坏键盘及其工具栏。工具栏从键盘“分离”并开始在屏幕顶部状态栏下方滑入和滑出。

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)
        }
    }
}    

我知道这很“hacky”,我只是偶然发现它,现在我很好奇为什么删除和添加视图会导致此行为。有人有想法吗? (它也发生在系统添加的工具栏上,例如在 webview 中)

这里很难看到,但您可以看到左侧的工具栏按钮:

removeFromSuperView() 方法将移除所有引用被移除视图的自动布局约束,以及该视图的子视图。它们不会因为您重新添加视图而神奇地重新存在,因此您最终会得到视图的框架恰好是什么。

虽然您是在这里进行试验,但您可以尝试这样做以查看视图是否恢复了它们的约束:

        for view in window.subviews {
            let constr = view.constraints
            view.removeFromSuperview()
            window.addSubview(view)
            NSLayoutConstraint.activate(constr)
        }

问题是总是有多个 windows,其中一个是 UITextEffectsWindow,它负责显示键盘(可能还有其他视图,因为它是私有的 API,没有任何官方文档。

在遍历 windows 时忽略 UITextEffectsWindow 将解决您的键盘问题。

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)
    }
}

但是由于 UITextEffectsWindow 是私有的 API,如果 window 是 UIWindow.[=15,也许你应该反过来,只删除视图=]