How to add a TextField to Alert in SwiftUI?

前端 未结 9 1932
温柔的废话
温柔的废话 2021-02-03 21:33

Anyone an idea how to create an Alert in SwiftUI that contains a TextField?

\"sample_image\"

9条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-03 21:47

    You can simply use UIAlertController directly. No need to roll your own alert dialog UI:

    private func alert() {
        let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
        alert.addTextField() { textField in
            textField.placeholder = "Enter some text"
        }
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in })
        showAlert(alert: alert)
    }
    
    func showAlert(alert: UIAlertController) {
        if let controller = topMostViewController() {
            controller.present(alert, animated: true)
        }
    }
    
    private func keyWindow() -> UIWindow? {
        return UIApplication.shared.connectedScenes
        .filter {$0.activationState == .foregroundActive}
        .compactMap {$0 as? UIWindowScene}
        .first?.windows.filter {$0.isKeyWindow}.first
    }
    
    private func topMostViewController() -> UIViewController? {
        guard let rootController = keyWindow()?.rootViewController else {
            return nil
        }
        return topMostViewController(for: rootController)
    }
    
    private func topMostViewController(for controller: UIViewController) -> UIViewController {
        if let presentedController = controller.presentedViewController {
            return topMostViewController(for: presentedController)
        } else if let navigationController = controller as? UINavigationController {
            guard let topController = navigationController.topViewController else {
                return navigationController
            }
            return topMostViewController(for: topController)
        } else if let tabController = controller as? UITabBarController {
            guard let topController = tabController.selectedViewController else {
                return tabController
            }
            return topMostViewController(for: topController)
        }
        return controller
    }
    

    Most of this code is just boilerplate to find the ViewController that should present the alert. Call alert() e.g. from the action of a button:

    struct TestView: View {
        var body: some View {
            Button(action: { alert() }) { Text("click me") }
         }
    }
    

    Please beware though that there seems to be a bug in beta 5 and onward that can sometimes cause the emulator to freeze once a text field is shown: Xcode 11 beta 5: UI freezes when adding textFields into UIAlertController

提交回复
热议问题