ViewControllerクラスを使用して、シングルビューアプリケーションプロジェクトを作成しました。自分のクラス内にある関数からUIAlertControllerを表示したいと思います。
これが私のクラスのアラートです。
class AlertController: UIViewController {
func showAlert() {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion: nil)
}
}
これがアラートを実行するViewControllerです。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func showAlertButton(sender: AnyObject) {
var alert = AlertController()
alert.showAlert()
}
}
これは、美しいアラートの代わりに取得するものです。
警告:Sprint1.AlertControllerでUIAlertController:0x797d2d20を表示しようとしています。そのビューがウィンドウ階層にない0x797cc500!
私は何をすべきか?
モーダルコントローラーからUIAlertController
をインスタンス化する場合は、viewDidAppear
ではなくviewDidLoad
で行う必要があります。そうしないとエラーが発生します。
これが私のコードです(Swift 4):
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alertController = UIAlertController(title: "Foo", message: "Bar", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}
ビュー階層を見てみましょう。 ViewController
があります。次に、AlertController
を作成し、それを階層に追加せず、その上でインスタンスメソッドを呼び出します。このメソッドは、AlertController
を別のコントローラー(UIAlertController
)だけを表示するコントローラーとして使用しようとします。
+ ViewController
+ AlertController (not in hierarchy)
+ UIAlertController (cannot be presented from AlertController)
コードを簡素化するには
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func showAlertButton(sender: AnyObject) {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion: nil)
}
}
これは動作します。
何かのためにAlertController
が必要な場合は、最初に階層に追加する必要があります。 addChildViewController
を使用するか、別のpresentViewController
呼び出しを使用します。
クラスをアラート作成の単なるヘルパーにしたい場合は、次のようになります。
class AlertHelper {
func showAlert(fromController controller: UIViewController) {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
controller.presentViewController(alert, animated: true, completion: nil)
}
}
と呼ばれる
var alert = AlertHelper()
alert.showAlert(fromController: self)
AnyClassにこれらのメソッドを含めるだけで、以下の関数を使用してアラートを呼び出すことができます
class func topMostController() -> UIViewController {
var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
while ((topController?.presentedViewController) != nil) {
topController = topController?.presentedViewController
}
return topController!
}
class func alert(message:String){
let alert=UIAlertController(title: "AppName", message: message, preferredStyle: .alert);
let cancelAction: UIAlertAction = UIAlertAction(title: "OK", style: .cancel) { action -> Void in
}
alert.addAction(cancelAction)
AnyClass.topMostController().present(alert, animated: true, completion: nil);
}
それから電話する
AnyClass.alert(message:"Your Message")
次の3行を記述します。必要なのはこれだけです。
Swift 3.
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
}
Swift 2.
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: flag, completion: completion)
}
このようなアラートを表示するための別のクラスを作成する場合は、UIViewControllerではなくNSObjectのサブクラスを作成します。
アラートビューを表示できるように、開始元のViewControllers参照をshowAlert関数に渡します。
Swift3のUtility.Swiftクラス(UIViewControllerではありません)のUIAlertControllerのコードを以下に示します。ありがとうございます。
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
}
func warningAlert(title: String, message: String ){
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { (action) -> Void in
}))
// self.present(alert, animated: true, completion: nil)
presentViewController(alert: alert, animated: true, completion: nil)
}
これは私のために働いた:
- (UIViewController *)topViewController{
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil) {
return rootViewController;
}
if ([rootViewController.presentedViewController isMemberOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
return [self topViewController:lastViewController];
}
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
return [self topViewController:presentedViewController];
}
実装:
UIViewController * topViewController = [self topViewController];
アラートで使用:
[topViewController presentViewController:yourAlert animated:YES completion:nil];
アプリの任意のクラスからアラートを送信できます(UIKitを使用する場合:#import <UIKit/UIKit.h>
)
それは、viewDidLoadメソッドとalertメソッドの起動の間にわずかな遅延をつけるのに役立ちました:
[self performSelector:@selector(checkPhotoPermission) withObject:nil afterDelay:0.1f];