Fra*_* P. 31 background uialertview uiactionsheet ios4 ios
Apple建议UIAlertViews/UIActionSheets
在iOS 4中进入后台状态时解除任何一个状态.这是为了避免用户在以后重新启动应用程序时出现任何混淆.我想知道如何能够立刻优雅地解雇所有UIAlertViews,而不是每次我设置它时都不保留对它的引用...
任何的想法 ?
小智 26
我的电话是为UIAlertview添加一个类别,添加以下功能:
- (void) hide {
[self dismissWithClickedButtonIndex:0 animated:YES];
}
Run Code Online (Sandbox Code Playgroud)
并承认UIApplicationWillResignActiveNotification
:
[[NSNotificationCenter defaultCenter] addObserver:alertView selector:@selector(hide) name:@"UIApplicationWillResignActiveNotification" object:nil];
Run Code Online (Sandbox Code Playgroud)
Gui*_*ume 24
我被爸爸的回答(有趣的用户名:) 所吸引,并且好奇为什么会被投票.
所以我试了一下.
这是UIAlertView子类的.m部分.
编辑:(Cédric)我添加了一种方法来捕获委托方法的调用并删除观察者然后避免多次注册到通知中心.
在这个github仓库中捆绑的所有东西:https://github.com/sdarlington/WSLViewAutoDismiss
#import "UIAlertViewAutoDismiss.h"
#import <objc/runtime.h>
@interface UIAlertViewAutoDismiss () <UIAlertViewDelegate> {
id<UIAlertViewDelegate> __unsafe_unretained privateDelegate;
}
@end
@implementation UIAlertViewAutoDismiss
- (id)initWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
self = [super initWithTitle:title
message:message
delegate:self
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil, nil];
if (self) {
va_list args;
va_start(args, otherButtonTitles);
for (NSString *anOtherButtonTitle = otherButtonTitles; anOtherButtonTitle != nil; anOtherButtonTitle = va_arg(args, NSString *)) {
[self addButtonWithTitle:anOtherButtonTitle];
}
privateDelegate = delegate;
}
return self;
}
- (void)dealloc
{
privateDelegate = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
[super dealloc];
}
- (void)setDelegate:(id)delegate
{
privateDelegate = delegate;
}
- (id)delegate
{
return privateDelegate;
}
- (void)show
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[super show];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
[super dismissWithClickedButtonIndex:[self cancelButtonIndex] animated:NO];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
}
#pragma mark - UIAlertViewDelegate
// The code below avoids to re-implement all protocol methods to forward to the real delegate.
- (id)forwardingTargetForSelector:(SEL)aSelector
{
struct objc_method_description hasMethod = protocol_getMethodDescription(@protocol(UIAlertViewDelegate), aSelector, NO, YES);
if (hasMethod.name != NULL) {
// The method is that of the UIAlertViewDelegate.
if (aSelector == @selector(alertView:didDismissWithButtonIndex:) ||
aSelector == @selector(alertView:clickedButtonAtIndex:))
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
return privateDelegate;
}
else {
return [super forwardingTargetForSelector:aSelector];
}
}
@end
Run Code Online (Sandbox Code Playgroud)
它工作得很好.这很棒,因为您可以像以前使用UIAlertView一样开始使用它.
我没有时间彻底测试它,但我没有注意到任何副作用.
小智 19
一种完全不同的方法是递归搜索.
应用程序委托的递归函数
- (void)checkViews:(NSArray *)subviews {
Class AVClass = [UIAlertView class];
Class ASClass = [UIActionSheet class];
for (UIView * subview in subviews){
if ([subview isKindOfClass:AVClass]){
[(UIAlertView *)subview dismissWithClickedButtonIndex:[(UIAlertView *)subview cancelButtonIndex] animated:NO];
} else if ([subview isKindOfClass:ASClass]){
[(UIActionSheet *)subview dismissWithClickedButtonIndex:[(UIActionSheet *)subview cancelButtonIndex] animated:NO];
} else {
[self checkViews:subview.subviews];
}
}
}
Run Code Online (Sandbox Code Playgroud)
从applicationDidEnterBackground过程调用它
[self checkViews:application.windows];
Run Code Online (Sandbox Code Playgroud)
Dad*_*Dad 12
呵呵.还没有尝试过这个,但是我想知道创建一个UIAlertView的子类是否有意义,它会监听这个Notification并关闭它自己......
这有"自动"而没有保留/保持特征OP正在请求.确保在关闭时取消注册通知(否则繁荣!)
pIk*_*kEL 12
正如评论中提到的那样:当我们拥有块时,接受的答案不是iOS 4.0以来最好/最干净的答案!我是这样做的:
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Alert!" message:@"This alert will dismiss when application resigns active!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification* notification){
[alert dismissWithClickedButtonIndex:0 animated:NO];
}];
Run Code Online (Sandbox Code Playgroud)
UIAlertView在iOS 8中被弃用,转而使用UIAlertController.不幸的是,这被证明是一个棘手的问题,因为接受的解决方案不起作用,因为Apple显然不支持子类化UIAlertController:
UIAlertController类旨在按原样使用,不支持子类化.此类的视图层次结构是私有的,不得修改.
我的解决方案是简单地遍历视图控制器树并关闭您找到的所有UIAlertControllers.您可以通过创建UIApplication的扩展然后在AppDelegate applicationDidEnterBackground
方法中调用它来全局启用它.
试试这个(在Swift中):
extension UIApplication
{
class func dismissOpenAlerts(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController)
{
//If it's an alert, dismiss it
if let alertController = base as? UIAlertController
{
alertController.dismissViewControllerAnimated(false, completion: nil)
}
//Check all children
if base != nil
{
for controller in base!.childViewControllers
{
if let alertController = controller as? UIAlertController
{
alertController.dismissViewControllerAnimated(false, completion: nil)
}
}
}
//Traverse the view controller tree
if let nav = base as? UINavigationController
{
dismissOpenAlerts(nav.visibleViewController)
}
else if let tab = base as? UITabBarController, let selected = tab.selectedViewController
{
dismissOpenAlerts(selected)
}
else if let presented = base?.presentedViewController
{
dismissOpenAlerts(presented)
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的AppDelegate中:
func applicationDidEnterBackground(application: UIApplication)
{
UIApplication.dismissOpenAlerts()
}
Run Code Online (Sandbox Code Playgroud)
我用以下代码解决了这个问题:
/* taken from the post above (Cédric)*/
- (void)checkViews:(NSArray *)subviews {
Class AVClass = [UIAlertView class];
Class ASClass = [UIActionSheet class];
for (UIView * subview in subviews){
NSLog(@"Class %@", [subview class]);
if ([subview isKindOfClass:AVClass]){
[(UIAlertView *)subview dismissWithClickedButtonIndex:[(UIAlertView *)subview cancelButtonIndex] animated:NO];
} else if ([subview isKindOfClass:ASClass]){
[(UIActionSheet *)subview dismissWithClickedButtonIndex:[(UIActionSheet *)subview cancelButtonIndex] animated:NO];
} else {
[self checkViews:subview.subviews];
}
}
}
/*go to background delegate*/
- (void)applicationDidEnterBackground:(UIApplication *)application
{
for (UIWindow* window in [UIApplication sharedApplication].windows) {
NSArray* subviews = window.subviews;
[self checkViews:subviews];
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
27998 次 |
最近记录: |