美文网首页
AlertView 注意点

AlertView 注意点

作者: kamto | 来源:发表于2018-09-18 18:01 被阅读25次

    在项目中遇到了一些关于alertView的小问题。虽然UIAlertView在iOS9.0已经过时了,在iOS8.0被新的UIAlertController所取代,但兼顾以前的系统UIAlertView仍然用得不少。

    1.

    使用UIAlertView弹窗时,如果接下来使用到[UIApplication sharedApplication].keyWindow来获取当前主屏幕时,系统会使用一个新的window来展现UIAlertView,当前keyWindow会被替换。

    [self.alertView show];
    NSLog(@"Class :  %@", NSStringFromClass([[UIApplication sharedApplication].keyWindow class]));
    NSLog(@"view Class :  %@", [UIApplication sharedApplication].keyWindow.rootViewController);
    

    会打印
    Class : _UIAlertControllerShimPresenterWindow
    Class : <UIApplicationRotationFollowingController: 0x1035358e0>

    而此时根据[UIApplication sharedApplication].keyWindow.rootViewController 将不是当前屏幕根控制器,如果此时在代理方法里再使用一个继承于UIWindow的子类时,如ToastView : UIWindow,此后获取keyWindow的时候keyWindow会被ToastView替换

    NSLog(@"Class :  %@", NSStringFromClass([[UIApplication sharedApplication].keyWindow class]));
    NSLog(@"view Class :  %@", [UIApplication sharedApplication].keyWindow.rootViewController);
    

    Class : ToastView
    Class : (null)

    所以我们应该避免在alertView弹窗时使用keyWindow,而是使用[UIApplication sharedApplication].delegate.window

    NSLog(@"Class :  %@", NSStringFromClass([[UIApplication sharedApplication].delegate.window class]));
    [self.alertView show];
    NSLog(@"Class :  %@", NSStringFromClass([[UIApplication sharedApplication].delegate.window class]));
    NSLog(@"view Class :  %@", [UIApplication sharedApplication].delegate.window.rootViewController);
    

    打印:
    Class : UIWindow
    Class : UIWindow
    Class : <ViewController: 0x135d0b700>

    总结:

    1、在UIAlertView没有show之前,delegate.window和keyWindow内存地址是一致的,表示当前的keyWindow就是应用的window,一般情况下,两者是同一个。
    2、在UIAlertView show之后,keyWindow发生了变化,已经被系统替换为新的window,这个新的window用来展示UIAlertView,但是此时delegate.window还是原来的那个。如果使用keyWindow的获取应用控制器的时候,最好将keyWindow改成delegate.window。

    2.

    使用UIAlertController则不会有这问题,弹窗时并不会改变keyWindow

    [self presentViewController:self.alertController animated:YES completion:nil];
    NSLog(@"Class :  %@", NSStringFromClass([[UIApplication sharedApplication].keyWindow class]));
    

    打印:
    Class : UIWindow

    3.

    如果要同时弹出多个alertview时
    如果使用UIAlertView,会先展现最新弹窗,点击消失后,继续弹出之前的弹窗,

    [alertView1 show];
    [alertView2 show];
    

    如果使用UIAlertController时,因为它继承UIViewController,它们的页面跳转都是使用的present方法。第一个UIAlertController跳转后,相当于当前最上层的页面是alertController1的页面,因此,此时想再增加一个UIAlertController,必须在alertController1上跳转。

    viewController presentViewController:alertController1 animated:YES completion:nil];
    [alertController1 presentViewController:alertController2 animated:YES completion:nil];
    
    4.

    当我们在键盘收起时使用alertView弹窗时会发现键盘收起马上alert弹窗,但收起alert时,键盘会出现并再收起。这是因为textField取消第一响应者后立刻执行弹出alert,打断键盘收起动画,在alert完后会再执行一遍键盘收起动画,解决办法是先需要获取键盘收起的时间,根据这个时间延迟执行alertView弹窗。使用UIAlertController则不会有这个问题。

    分享一道面试题

    @interface Son : Father
    
    @end
    
    - (instancetype)init{
        if (self = [super init]) {
            NSLog(@"%@", NSStringFromClass([self class]));
            NSLog(@"%@", NSStringFromClass([super class]));
        }
        return self;
    }
    

    都会打印:
    Son
    Son

    原因:

    调用[self class]的时候会去self的isa所指向的Son类对象中寻找该方法,在没有重载[obj class]的情况下, Son类对象是没有这个方法的,此时会接着在父类对象的方法列表中查找,最终会发现NSObject存储了该方法,所以[self class]会返回实例对象(self)所属的Son这个类对象。

    [super class]则指定从父类Father的方法列表开始去查找- (Class)class这个方法,显然Father没有这个方法,最终还是要查找到NSObject类对象的方法列表中,需要注意的是不管是[self class]还是[super class], 它们都是调用的实例对象的- (Class)class方法,虽然其指向的类对象不同,但实例对象都是self本身,再强调下区分开实例对象和类对象!因而返回的也是当前self的isa所指向的Son类。super是objc_super类型的结构体,它包含了当前的实例对象self以及父类的类对象。

    相关文章

      网友评论

          本文标题:AlertView 注意点

          本文链接:https://www.haomeiwen.com/subject/xiqmnftx.html