有没有办法告诉 iOS 在视图控制器中更新键盘外观?

Is there a way to tell iOS to update the keyboard appearance within a view controller?

我想在 ViewController 内更新 UIKeyboardAppearance。我的意思是说 VC 加载 UIKeyboardAppearance.default。如果我按下一个按钮,我希望键盘更新为 .dark 并且键盘现在显示为与 .dark.

相同的 VC

据我所知,iOS 在加载 VC 时检查 UIKeyboardAppearance 的值,并且在加载 VC 之前不会再次检查再次。即使你改变UIKeyboardAppearance和hide/show键盘的值。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

// creating a simple text box, and making the placeholder text the value of the keyboardAppearance
        myTextBox.backgroundColor = UIColor.lightGray
        myTextBox.frame = CGRect(x: 30, y: 200, width: 300, height: 50)
        view.addSubview(myTextBox)
        UITextField.appearance().keyboardAppearance = .dark
        myTextBox.becomeFirstResponder()
        myTextBox.placeholder = "Keybaoard Appearance is: \(UITextField.appearance().keyboardAppearance.rawValue)"

// a simple button to toggle the keyboardAppearance
        toggleButton.frame = CGRect(x: 30, y: 300, width: 300, height: 50)
        toggleButton.setTitle("Toggle Keyboard", for: .normal)
        toggleButton.backgroundColor = UIColor.red
        toggleButton.addTarget(self, action: #selector(toggleButtonFunction), for: .touchUpInside)
        view.addSubview(toggleButton)

    }

// toggles the keyboardAppearance. Hides the keyboard, and a second later shows it again.
    @objc func toggleButtonFunction() {
        if UITextField.appearance().keyboardAppearance == .dark {
            UITextField.appearance().keyboardAppearance = .default
        }
        else {
            UITextField.appearance().keyboardAppearance = .dark
        }
        myTextBox.resignFirstResponder()
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1), execute: {
            self.myTextBox.becomeFirstResponder()
            self.myTextBox.placeholder = "Keybaoard Appearance is: \(UITextField.appearance().keyboardAppearance.rawValue)"

            })
    }

    let myTextBox = UITextField()
    let toggleButton = UIButton()
}

我希望在更改 UIKeyboardAppearance 和 hiding/showing 键盘后它会显示新的外观(.dark.default),但它不断显示具有相同的外观,直到再次加载 VC。您可以看到 UIKeyboardAppearance 的值发生变化,但 iOS 似乎不会检查该更新,直到 VC 再次加载。

有什么方法可以在 VC 内强制重新检查?

感谢您的帮助!

您可以在屏幕上递归更改所有文本字段的键盘外观(allSubviewsOf(type:) 扩展名来自 ):

func changeTextFieldKeyboardAppearance() {
    UITextField.appearance().keyboardAppearance = .dark

    let textFields = view.allSubviewsOf(type: UITextField.self)

    let firstResponder = textFields.first { [=10=].isFirstResponder }

    firstResponder?.resignFirstResponder()

    textFields.forEach { [=10=].keyboardAppearance = .dark }

    firstResponder?.becomeFirstResponder()
}

[...]

extension UIView {
    func allSubviewsOf<T: UIView>(type: T.Type) -> [T] {
        var all = [T]()

        func getSubview(view: UIView) {
            if let aView = view as? T {
                all.append(aView)
            }

            guard !view.subviews.isEmpty else {
                return
            }

            view.subviews.forEach{ getSubview(view: [=10=]) }
        }

        getSubview(view: self)

        return all
    }
}

如果您的视图控制器嵌入在 UITabBarController 中,您可以通过更改其 selectedIndex 并立即将其更改回原始索引来触发更新:

guard let tabBarController = tabBarController else {
    return
}

let selectedIndex = tabBarController.selectedIndex

UITextField.appearance().keyboardAppearance = .dark

tabBarController.selectedIndex = selectedIndex == 1 ? 0 : 1
tabBarController.selectedIndex = selectedIndex

感谢 Tamás 的回答!

它让我找到了我需要的东西。

如果您更改 UITextField 的 keyboardAppearance 看起来像是

UITextField.appearance().keyboardAppearance = .dark

系统只检查 VC 负载。如果您为每个 textField

更改它
myTextBox.keyboardAppearance = .dark

每次 firstResponder 更改时系统都会检查并加载正确的键盘。

再次感谢 Tamás!