如何显示来自其他班级的警报

时间:2017-09-13 02:14:55

标签: ios swift swift3 uialertcontroller

我创建了一个Utilities类来保存一些常用函数,其中一个是一个alertUser函数,如果调用它,它将向用户显示一个Alert框,其中包含提供的标题和消息文本。在另一个类文件中,我正在验证一些文本字段条目,如果验证没有通过,那么我想使用Utilities类中的alertUser函数。但是,当我这样做时,我在Xcode日志中收到以下错误消息:

Warning: Attempt to present <UIAlertController: 0x7f9c4be0b140> on <MyAppName.Utilities: 0x7f9c4be1cb60> whose view is not in the window hierarchy!

调用代码位于UIViewController类文件中。这是代码中的代码 class ItemSettingsVC:UIViewController:

private func validateNameField() -> Bool {
    var passed = false

    if (nameField.hasText) {
        passed = true
    } else {
        Utilities().alertUser(strTitle: "Alert", strMessage: strInvalidNameFieldErrorMsg)
        passed = false
    }
    return passed
}

这里是alertUser函数 class Utilities:UIViewController:

public func alertUser(strTitle: String, strMessage: String) {
    let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
    myAlert.addAction(okAction)
    self.present(myAlert, animated: true, completion: nil)
}

这是在iOS上运行的。我正在使用Xcode 8和swift 3.非常感谢任何帮助。感谢。

4 个答案:

答案 0 :(得分:2)

这应该这样做:

public func alertUser(strTitle: String, strMessage: String) {
    let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
    myAlert.addAction(okAction)
    UIApplication.shared.delegate?.window??.rootViewController?.present(myAlert, animated: true, completion: nil)
}

答案 1 :(得分:1)

您必须在 alertUser 功能中添加其他参数,该功能将是将显示警报控制器的VC。

例如:

public func alertUser(strTitle: String, strMessage: String, viewController: UIViewController) {
    let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
    myAlert.addAction(okAction)
    viewController.present(myAlert, animated: true, completion: nil)
}

但我建议你只需要扩展 UIViewController 并在那里添加你的 func alertUser()* ,因为你肯定会使用在我看来,这个alertUser在不同的VC和复杂性方面,这将更加优化。

像这样:

extension UIViewController {

  func showAlert(title: String, message: String, callback: @escaping () -> ()) {
     let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
     alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {
       alertAction in
       callback()
     }))

     self.present(alert, animated: true, completion: nil)
   }

   //add additional functions here if necessary
   //like a function showing alert with cancel
}

注意:请不要将您的Utilities类作为UIViewController的子类,最好使其成为 struct 处理静态函数和/或变量

答案 2 :(得分:1)

使用此类可以轻松显示Alert或ActionSheet

UIAlertController Extension

public extension UIAlertController {
    public func showAlert(animated: Bool = true, completionHandler: (() -> Void)? = nil) {
        guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else {
            return
        }
        var forefrontVC = rootVC
        while let presentedVC = forefrontVC.presentedViewController {
            forefrontVC = presentedVC
        }
        forefrontVC.present(self, animated: animated, completion: completionHandler)
    }
}

AppAlert类为UIAlertController Show创建

public class AppAlert {
    private var alertController: UIAlertController

    public init(title: String? = nil, message: String? = nil, preferredStyle: UIAlertControllerStyle) {
        self.alertController = UIAlertController(title: title, message: message, preferredStyle: preferredStyle)
    }

    public func setTitle(_ title: String) -> Self {
        alertController.title = title
        return self
    }

    public func setMessage(_ message: String) -> Self {
        alertController.message = message
        return self
    }

    public func setPopoverPresentationProperties(sourceView: UIView? = nil, sourceRect:CGRect? = nil, barButtonItem: UIBarButtonItem? = nil, permittedArrowDirections: UIPopoverArrowDirection? = nil) -> Self {

        if let poc = alertController.popoverPresentationController {
            if let view = sourceView {
                poc.sourceView = view
            }
            if let rect = sourceRect {
                poc.sourceRect = rect
            }
            if let item = barButtonItem {
                poc.barButtonItem = item
            }
            if let directions = permittedArrowDirections {
                poc.permittedArrowDirections = directions
            }
        }

        return self
    }

    public func addAction(title: String = "", style: UIAlertActionStyle = .default, handler: @escaping ((UIAlertAction!) -> Void) = { _ in }) -> Self {
        alertController.addAction(UIAlertAction(title: title, style: style, handler: handler))
        return self
    }

    public func addTextFieldHandler(_ handler: @escaping ((UITextField!) -> Void) = { _ in }) -> Self {
        alertController.addTextField(configurationHandler: handler)
        return self
    }

    public func build() -> UIAlertController {
        return alertController
    }
}

用于打开AlertBox

AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .alert)
    .addAction(title: "NO", style: .cancel) { _ in
        // action
    }
    .addAction(title: "Okay", style: .default) { _ in
         // action
    }
    .build()
    .showAlert(animated: true)

用于ActionSheet打开

if UIDevice.current.userInterfaceIdiom != .pad {
    // Sample to show on iPhone
    AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .actionSheet)
        .addAction(title: "NO", style: .cancel) {_ in
            print("No")
        }
        .addAction(title: "YES", style: .default) { _ in
            print("Yes")
        }
        .build()
        .showAlert(animated: true)
} else {
    // Sample to show on iPad
    AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .actionSheet)
        .addAction(title: "Not Sure", style: .default) {
            _ in
            print("No")
        }
        .addAction(title: "YES", style: .default) { _ in
           print("Yes")
        }
        .setPopoverPresentationProperties(sourceView: self, sourceRect: CGRect.init(x: 0, y: 0, width: 100, height: 100), barButtonItem: nil, permittedArrowDirections: .any)
        .build()
        .showAlert(animated: true)
}

答案 3 :(得分:0)

首先找出窗口上最顶层的viewController。

Get the top ViewController in iOS Swift

然后在viewController上显示你的警报。不需要传递任何参数。

public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
topmostVC().present(myAlert, animated: true, completion: nil)

}