Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/105.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何显示来自不同类别的警报_Ios_Swift_Swift3_Uialertcontroller - Fatal编程技术网

Ios 如何显示来自不同类别的警报

Ios 如何显示来自不同类别的警报,ios,swift,swift3,uialertcontroller,Ios,Swift,Swift3,Uialertcontroller,我创建了一个实用程序类来保存一些常用函数,其中一个是alertUser函数,如果调用该函数,将向用户显示一个带有提供的标题和消息文本的警报框。在另一个类文件中,我正在验证一些文本字段条目,如果验证没有通过,那么我想使用Utilities类中的alertUser函数。但是,执行此操作时,我在Xcode日志中收到以下错误消息: Warning: Attempt to present <UIAlertController: 0x7f9c4be0b140> on <MyAppName.

我创建了一个实用程序类来保存一些常用函数,其中一个是alertUser函数,如果调用该函数,将向用户显示一个带有提供的标题和消息文本的警报框。在另一个类文件中,我正在验证一些文本字段条目,如果验证没有通过,那么我想使用Utilities类中的alertUser函数。但是,执行此操作时,我在Xcode日志中收到以下错误消息:

Warning: Attempt to present <UIAlertController: 0x7f9c4be0b140> on <MyAppName.Utilities: 0x7f9c4be1cb60> whose view is not in the window hierarchy!
下面是alertUser函数,它位于 类实用程序:UIViewController:

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

    if (nameField.hasText) {
        passed = true
    } else {
        Utilities().alertUser(strTitle: "Alert", strMessage: strInvalidNameFieldErrorMsg)
        passed = false
    }
    return passed
}
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。非常感谢您的帮助。谢谢。

您必须在alertUser函数中添加一个附加参数,该参数将是显示alert控制器的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()*,因为您肯定会在不同的VCs中使用此alertUser,而且在我看来,这将更加优化

像这样:

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
}
注意:请不要将实用程序类设置为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)
    UIApplication.shared.delegate?.window??.rootViewController?.present(myAlert, animated: true, completion: nil)
}

首先找出窗口上最上面的viewController

然后在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)
}

使用此类可轻松显示警报或行动表 UIAlertController扩展

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)
    }
}
为UIAlertController Show创建AppAlert类

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)
用于打开行动表

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

我已经给出了一个答案,但我也只是想在这里发表评论,以避免混淆您应该做什么。为了回答您关于崩溃的问题,这是因为您的实用程序(UIViewController的子类)不是前台的当前视图,它试图通过调用self来显示警报控制器。这就是为什么我推荐下面的答案。还要注意最后一条信息:)