不在视图控制器中时如何呈现 UIAlertController?

编程入门 行业动态 更新时间:2024-10-28 05:27:24
本文介绍了不在视图控制器中时如何呈现 UIAlertController?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

场景:用户点击视图控制器上的按钮.视图控制器是导航堆栈中的最顶层(显然).Tap 调用在另一个类上调用的实用程序类方法.那里发生了一件坏事,我想在控制权返回到视图控制器之前在那里显示警报.

Scenario: The user taps on a button on a view controller. The view controller is the topmost (obviously) in the navigation stack. The tap invokes a utility class method called on another class. A bad thing happens there and I want to display an alert right there before control returns to the view controller.

+ (void)myUtilityMethod { // do stuff // something bad happened, display an alert. }

使用 UIAlertView 可以做到这一点(但可能不太合适).

This was possible with UIAlertView (but perhaps not quite proper).

在这种情况下,您如何在 myUtilityMethod 中呈现 UIAlertController?

In this case, how do you present a UIAlertController, right there in myUtilityMethod?

推荐答案

在 WWDC,我在其中一个实验室停下来问了一位 Apple 工程师同样的问题:显示 的最佳做法是什么?UIAlertController?"他说他们经常收到这个问题,我们开玩笑说他们应该就这个问题进行一次会议.他说,Apple 在内部创建了一个带有透明 UIViewController 的 UIWindow,然后在其上呈现 UIAlertController.基本上是 Dylan Betterman 的回答.

At WWDC, I stopped in at one of the labs and asked an Apple Engineer this same question: "What was the best practice for displaying a UIAlertController?" And he said they had been getting this question a lot and we joked that they should have had a session on it. He said that internally Apple is creating a UIWindow with a transparent UIViewController and then presenting the UIAlertController on it. Basically what is in Dylan Betterman's answer.

但我不想使用 UIAlertController 的子类,因为这需要我在整个应用程序中更改代码.因此,在关联对象的帮助下,我在 UIAlertController 上创建了一个类别,该类别在 Objective-C 中提供了一个 show 方法.

But I didn't want to use a subclass of UIAlertController because that would require me changing my code throughout my app. So with the help of an associated object, I made a category on UIAlertController that provides a show method in Objective-C.

相关代码如下:

#import "UIAlertController+Window.h" #import <objc/runtime.h> @interface UIAlertController (Window) - (void)show; - (void)show:(BOOL)animated; @end @interface UIAlertController (Private) @property (nonatomic, strong) UIWindow *alertWindow; @end @implementation UIAlertController (Private) @dynamic alertWindow; - (void)setAlertWindow:(UIWindow *)alertWindow { objc_setAssociatedObject(self, @selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UIWindow *)alertWindow { return objc_getAssociatedObject(self, @selector(alertWindow)); } @end @implementation UIAlertController (Window) - (void)show { [self show:YES]; } - (void)show:(BOOL)animated { self.alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.alertWindow.rootViewController = [[UIViewController alloc] init]; id<UIApplicationDelegate> delegate = [UIApplication sharedApplication].delegate; // Applications that does not load with UIMainStoryboardFile might not have a window property: if ([delegate respondsToSelector:@selector(window)]) { // we inherit the main window's tintColor self.alertWindow.tintColor = delegate.window.tintColor; } // window level is above the top window (this makes the alert, if it's a sheet, show over the keyboard) UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject; self.alertWindow.windowLevel = topWindow.windowLevel + 1; [self.alertWindow makeKeyAndVisible]; [self.alertWindow.rootViewController presentViewController:self animated:animated completion:nil]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; // precaution to ensure window gets destroyed self.alertWindow.hidden = YES; self.alertWindow = nil; } @end

这是一个示例用法:

// need local variable for TextField to prevent retain cycle of Alert otherwise UIWindow // would not disappear after the Alert was dismissed __block UITextField *localTextField; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Global Alert" message:@"Enter some text" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { NSLog(@"do something with text:%@", localTextField.text); // do NOT use alert.textfields or otherwise reference the alert in the block. Will cause retain cycle }]]; [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { localTextField = textField; }]; [alert show];

当 UIAlertController 被释放时,创建的 UIWindow 将被销毁,因为它是唯一保留 UIWindow 的对象.但是,如果您将 UIAlertController 分配给一个属性或通过访问其中一个操作块中的警报导致其保留计数增加,UIWindow 将保留在屏幕上,锁定你的用户界面.在需要访问UITextField的情况下,请参阅上面的示例使用代码.

The UIWindow that is created will be destroyed when the UIAlertController is dealloced, since it is the only object that is retaining the UIWindow. But if you assign the UIAlertController to a property or cause its retain count to increase by accessing the alert in one of the action blocks, the UIWindow will stay on screen, locking up your UI. See the sample usage code above to avoid in the case of needing to access UITextField.

我用一个测试项目制作了一个 GitHub 存储库:FFGlobalAlertController

I made a GitHub repo with a test project: FFGlobalAlertController

更多推荐

不在视图控制器中时如何呈现 UIAlertController?

本文发布于:2023-11-27 19:30:10,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1639311.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:视图   控制器   中时   UIAlertController

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!