iOS 引用当前显示的UIAlertView

UIAlertView在iOS里和一般的UIView不一样,有时候使用起来会有一些不便。特别要引用当前显示的UIAlertView的时候,就存在一些难度。

UIAlertView

在iOS7以前

可以下面的代码可以解决这个问题:

#pragma mark 查找当前界面有没有一个AlertView
+(BOOL)isAlert{
    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        NSArray* subviews = window.subviews;
        if ([subviews count] > 0)
            if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
                return YES;
    }
    return NO;
}
#pragma mark 关闭当前界面上的alertView
+(void)closeAlert{
    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        NSArray* subviews = window.subviews;
        if ([subviews count] > 0)
            if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
                [[subviews objectAtIndex:0] dismissWithClickedButtonIndex:0 animated:YES];
    }
}

可以把它放在一个公用的类中作为静态方法调用,使用起来非常方便。不幸的是,iOS7以后不能使用了。事实上,在iOS7以后,UIAlertView已经不属于任何一个window了,-[UIAlertView window]的值一直是nil。 而且alert view 的管理方法在开发文档里也没有列出来。这意味着,即使遍历整个windows的subviews,也找不到AlertView。

判断当前keyWindow

/// 查找当前界面有没有一个AlertView.
+(BOOL)isAlert{
    if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])
    {
        ////There is no alertview present
        return  NO;
    }
    return YES;
}

这个方法看起来是比较简单的,可惜无法引用到UIAlertView,就无法用代码关闭它。我尝试用

if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])

{

////There is no alertview present

return ;

}

UIAlertView* alert=(UIAlertView*)[UIApplication sharedApplication].keyWindow;

这样的代码,但是失败了。

国外有提出下面的iOS7处理方案:

Class UIAlertManager = objc_getClass("_UIAlertManager");
UIAlertView *topMostAlert = [UIAlertManager performSelector:@selector(topMostAlert)];

我没有成功运行这个代码,最重要原因我希望能写一个公用的方法获取当前的UIAlertView,所以这个方法我不感兴趣。

上面代码也可以这样写:

 UIAlertView *topMostAlert = [NSClassFromString(@"_UIAlertManager") performSelector:@selector(topMostAlert)]; 

感兴趣的同学可以试一下。但据说这个方法Apple Store是不会审核通过的,因为它用到的是未公开的方法。

在当前ViewController定义一个isAlertView变量

这个方法原理比较简单,但使用起来挺麻烦。

// initialize default flag for alert... If alert is not open set isOpenAlert as NO
BOOL isAlertOpen;
isAlertOpen = NO;
if (isAlertOpen == NO) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Alert is Open" delegate:self cancelButtonTitle:@"Okay!!" otherButtonTitles: nil];
    [alert show];
    // Now set isAlertOpen to YES
    isAlertOpen = YES;
}
else
{
    //Do something
}

使用Notification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(aWindowBecameVisible:) name:UIWindowDidBecomeVisibleNotification object:nil];

然后在aWindowBecameVisible里验证:

if ([[theWindow description] hasPrefix:@"<_UIModalItemHostingWin"])
{
    // This is the alert window
}

这个方法也有点麻烦。

在AppDelegate定义公用变量

在AppDelegate.h里:

@property (nonatomic, assign) BOOL isAlertVisibleOnAppWindow;

在使用UIAlertView的时候:

AppDelegate *delegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
if (!delegate.isAlertVisibleOnAppWindow) {
    delegate.isAlertVisibleOnAppWindow = YES;

    UIAlertView *alertView = [[UIAlertView alloc] init…//alert init code

}

在按钮的点击事件里,要给isAlertVisibleOnAppWindow再赋值。

这方法也不容易。

自定义一个MyUIAlertView

使用一个static BOOL alertIsShowing变量,然后override -(void)show selector.

在show的时候,就可以判断当前alertIsShowing的值。

而且可以自己定义一个close方法。

UIAlertController

苹果官方文档介绍,UIAlertView在iOS8以后不赞成再继续使用,同样UIAlertViewDelegate可能也要废弃了。使用UIAlertController来替代UIAlertView。关于UIAlertController的用法我在下一篇博文里介绍,这里还是尝试能否查找到现有UIAlertController。下面的代码经测试可以成功运行:

@implementation StringUtils
/// 查找当前界面有没有一个AlertView.
+(BOOL)isAlert{
    if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])
    {
        return  NO;
    }
    return YES;
}

/// 关闭当前界面上的alertView.
+(void)closeAlert{
    UIViewController* c=[self activityViewController];
    if([c isKindOfClass:[UIAlertController class]]){
        NSLog(@"success");
    }
    else if([c isKindOfClass:[UINavigationController class]]){
        UINavigationController* d =(UINavigationController*)c;

        if([d.visibleViewController isKindOfClass:[UIAlertController class]]){
            UIAlertController* control=(UIAlertController*)d;
            [control dismissViewControllerAnimated:YES completion:^{}];
            NSLog(@"success again");
        }
    }
}
/// 查找当前活动窗口.
+ (UIViewController *)activityViewController
{
    UIViewController* activityViewController = nil;

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    if(window.windowLevel != UIWindowLevelNormal)
    {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(UIWindow *tmpWin in windows)
        {
            if(tmpWin.windowLevel == UIWindowLevelNormal)
            {
                window = tmpWin;
                break;
            }
        }
    }

    NSArray *viewsArray = [window subviews];
    if([viewsArray count] > 0)
    {
        UIView *frontView = [viewsArray objectAtIndex:0];

        id nextResponder = [frontView nextResponder];

        if([nextResponder isKindOfClass:[UIViewController class]])
        {
            activityViewController = nextResponder;
        }
        else
        {
            activityViewController = window.rootViewController;
        }
    }

    return activityViewController;
}
@end

调用时,使用

[StringUtils closeAlert];

即可关闭当前打开的UIAlertController窗口。

时间: 2024-10-07 05:51:30

iOS 引用当前显示的UIAlertView的相关文章

【iOS开发每日小笔记(四)】iOS 7中如何除去UIAlertView 规避delegate对象销毁后接收消息的crash

这篇文章是我的[iOS开发每日小笔记]系列中的一片,记录的是今天在开发工作中遇到的,可以用很短的文章或很小的demo演示解释出来的小心得小技巧.该分类的文章,内容涉及的知识点可能是很简单的.或是用很短代码片段就能实现的,但在我看来它们可能会给用户体验.代码效率得到一些提升,或是之前自己没有接触过的技术,很开心的学到了,放在这里得瑟一下.其实,90%的作用是帮助自己回顾.记忆.复习.如果看官觉得太easy,太碎片,则可以有两个选择:1,移步[iOS探究]分类,对那里的文章进行斧正:2,在本文的评论

iOS系统自带的 UIAlertView 自动旋转的实现

这里主要解析 UIAlertView 的几个关键功能的实现: 随着设备屏幕的旋转而旋转: Alert弹出框,使用UIWindow来实现,就是说,不用依赖于当前显示在最前面的UIView. 实现源码参考: http://git.oschina.net/shede333/BMAlertHud 使用UIWindow 弹出一个Alert框,最好新建一个 UIWIndow, 把window.windowLevel = UIWindowLevelAlert,这样就能显示在最前面: 调用[window mak

iOS系统自带的 **UIAlertView** 以及 屏幕自动旋转的实现

iOS系统自带的 UIAlertView 自动旋转的实现 这里主要解析 UIAlertView 的几个关键功能的实现: 随着设备屏幕的旋转而旋转: Alert弹出框,使用UIWindow来实现,就是说,不用依赖于当前显示在最前面的UIView. 实现源码参考: http://git.oschina.net/shede333/BMAlertHud 使用UIWindow 弹出一个Alert框,最好新建一个 UIWIndow, 把window.windowLevel = UIWindowLevelAl

IOS 键盘的显示与关闭,以及移动显示(UITextView处理完整版)

IOS 键盘的显示与关闭 在每一个IOS应用中,几乎不可避免的要进行文本输入操作,例如要求用户填写登陆注册信息,进行话题的评论回复,等等.用到的文本输入组件有UITextField,UITextView,对于这两个组件的相关属性和方法想必大家都很熟悉,但貌似对于键盘的显示或隐藏过程貌似常常不是很清楚,其实本人也是一知半解,所以趁此做简单的总结,基本上以下描述出自于官方的文档,并没有什么更改. 1.开启键盘面板 当用户触击某一个view时,系统会自动指定该view为第一响应对象(first res

iOS常用于显示几小时前/几天前/几月前/几年前的代码片段

iOS常用于显示几小时前/几天前/几月前/几年前的代码片段 2015-03-13 10:09 版权声明:请关注个人博客:http://www.henishuo.com/ print? /** * Retain a formated string with a real date string * * @param dateString a real date string, which can be converted to a NSDate object * * @return a strin

ios设置中显示自己的应用

1.建立一个setting bundle文件.如图: 2.会出现一个文件,打开Root.plist文件,对plist文件中的值进行设置. 3.其中设置中又6种样式. Group      开头的title Multi value Slider    拖拉设置 TextField   文本框 Title         文本 Toggle Switch 开关控件 4.代码实现,可以在程序内获取设置值. 在程序员中加入 NSUserDefaults *defaults = [NSUserDefaul

iOS开发- iOS7显示偏差(UITableView下移)解决办法

之前碰到过一个问题. 就是利用storyboard拖动出来的控件, 在iOS7上跑老是莫名的下移. 比如这样(红色区域为多余的) 解决办法: iOS7在Conttoller中新增了这个属性: automaticallyAdjustsScrollViewInsets,当设置为YES时(默认YES),如果视图里面存在唯一一个UIScrollView或其子类View,那么它会自动设置相应的内边距,这样可以让scroll占据整个视图,又不会让导航栏遮盖. 我们设置automaticallyAdjusts

IOS页面UILable显示多行文本

IOS页面UILable显示多行文本 最近有遇到过多行显示文本的问题 都是使用的uitextview来做到的  处理麻烦需要关闭滚动 还有输入等响应 而且本身uitextview控件比label大几倍 偶然无疑间发现了别人博客中的一个方法 转过来分享下 UILabel*label; //设置换行label.lineBreakMode = UILineBreakModeWordWrap; label.numberOfLines = 0; 换行符还是\n比如NSString * [email pro

iOS 输入地点 显示当前位置地图并用大头针标注

废话不多说 直接上项目工程  ,还是 先看下效果图吧! 项目中有两个文件,chonViewController 和mapLocation文件 ,mapLocation 文件用于地标显示 并有附加信息,昨天做得时候附加信息显示正常,今天想写点博客 却不显示了 ,很郁闷! 新建工程后 记得加入类库,MapKit.framework 具体添加方法 这里不在说明了 下面 看下 chonViewController.h 文件 代码如下: #import <UIKit/UIKit.h> #import &