Dolly_洋的iOS的成长之路——UIWindow的理解与运用

说到UIWindow,首先要清楚以下几点:

    1.UIWindow是最顶层的界面容器,并继承自UIView。


    2.UIWindow基本方法,

    显示:myWindow.hidden = NO;

    消失:myWindow.hidden = YES;

    [myWindow makeKeyWindow];  //将window设置成主keyWindow,是被系统设计用来接收键盘和其他非触摸事件的window。

    [myWindow resignKeyWindow];

    [myWindow makeKeyAndVisible];//相当于 [myWindow makeKeyWindow];myWindow.hidden = NO;

系统默认会有一个window,显示是用的- (void)makeKeyAndVisible;// convenience. most apps call this to show the main window and also make it key. otherwise use view hidden property.

     这个方法,是为了更方便的让window显示并设置成keyWindow,否则,就要用前面说的[myWindow makeKeyWindow];myWindow.hidden = NO;这两行代码。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window setRootViewController:[[GesturePasswordController alloc] init]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}


    3.平常经常用到的UIWindow的情况:UIStatusbar 、 UIAlertView 、UIActionSheet  、键盘

    首先,它们不是UIWindow!前面说了,UIWIndow是最顶层的界面容器,每当上面的控件出现的时候,系统会自动生成一个UIWindow,然后把这个视图加到相应的window中,再让window显示。仔细体会一下以上控件出现时的效果,是不是觉得UIWindow也不是那么抽象了呢。

    现在,我们思考一个问题,当UIAlertView执行show的方法时,为什么会出现在最上层呢,系统不是有一个默认的window了吗,对,现在就要讲UIWindow的层级(UIWindowLevel)的概念。


    4.UIWindowLevel

    UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal;
     UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert;
     UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar;  

     NSLog(@"UIWindowLevelNormal = %f,UIWindowLevelStatusBar = %f,UIWindowLevelAlert = %f",UIWindowLevelNormal,UIWindowLevelStatusBar,UIWindowLevelAlert);

     输出一下这三个值会发现UIWindowLevelNormal = 0.000000

                                             UIWindowLevelStatusBar = 1000.000000

                                             UIWindowLevelAlert = 2000.000000

     默认程序的window的windowLevel属性是UIWindowLevelNormal,UIAlertView对应的window.windowLevel = UIWindowLevelAlert,这就说明了哪个window层级越大,哪个window就会被显示在界面最上面。

     当然,如果你想创建个window,让它还在UIAlertView之上,只需window.windowLevel = 2001.000000; //层级比alertVIew大,会覆盖在界面最上层。


    5.思考下什么情况我们需要自己创建window。我们想一个场景,比如支付宝,在任何界面每次按Home键退出,再进来,就需要重新输入手势密码。这就很适合用UIWindow做,因为这个界面有可能从任何界面弹出,并且盖到所有界面的最上层,当然,也有其他的办法,下面就是实例代码(手势密码用的GesturePassword,https://github.com/smilingxinyi/GesturePassword)

//自定义继承自window的类声明部分

#import <UIKit/UIKit.h>
#import <Security/Security.h>
#import <CoreFoundation/CoreFoundation.h>
#import "TentacleView.h"
#import "GesturePasswordView.h"
#import "KeychainItemWrapper.h"
@interface GesturePasswordVertifyWindow : UIWindow<VerificationDelegate>
+(GesturePasswordVertifyWindow*)sharedInstance;
-(void)show;
@end


//自定义继承自window的类实现部分

#import "GesturePasswordVertifyWindow.h"
static GesturePasswordVertifyWindow * sharedWindow = nil;
@implementation GesturePasswordVertifyWindow
{
    NSString            * password;
    GesturePasswordView * gesturePasswordView;
}
+(GesturePasswordVertifyWindow*)sharedInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedWindow = [[self alloc]initWithFrame:[UIScreen mainScreen].bounds];
    });
    return sharedWindow;
}
-(instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if(self){
        //取到之前设置的手势密码
        KeychainItemWrapper * keychin = [[KeychainItemWrapper alloc]initWithIdentifier:@"Gesture" accessGroup:nil];
        password = [keychin objectForKey:(__bridge id)kSecValueData];
        //将验证手势密码的view添加到当前window
        gesturePasswordView = [[GesturePasswordView alloc]initWithFrame:[UIScreen mainScreen].bounds];
        [gesturePasswordView.tentacleView setRerificationDelegate:self];
        [gesturePasswordView.tentacleView setStyle:1];
        [self addSubview:gesturePasswordView];
    }
    return self;
}
-(void)show{
    //当重新进入程序时,调用show方法,显示当前window,覆盖到整个界面之上,起到安全的作用
    [self makeKeyWindow]; //这里可以不设置成keyWindow,但是如果window需要弹出键盘了必须设置,
    self.hidden = NO;
}
#pragma mark --- VerificationDelegate代理方法
- (BOOL)verification:(NSString *)result{
    if ([result isEqualToString:password]) {
        [gesturePasswordView.state setTextColor:[UIColor colorWithRed:2/255.f green:174/255.f blue:240/255.f alpha:1]];
        [gesturePasswordView.state setText:@"输入正确"];
        //密码正确当前window消失
        [self resignKeyWindow];
         self.hidden = YES;
        return YES;
    }
    else{
        [gesturePasswordView.state setTextColor:[UIColor redColor]];
        [gesturePasswordView.state setText:@"手势密码错误"];
        return NO;
    }
}
@end

   


我们只需要在应用进入前台的回调函数中,调用该window的show方法即可,代码如下:

-(void)applicationDidBecomeActive:(UIApplication*)application{

   [[ GesturePasswordVertifyWindow sharedInstance]show];

}

还有很多种情况也可以使用UIWindow,比如广告,启动页等,就不一一介绍了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值