UIWindow使用介紹,uiwindow介紹
我們在平時的開發過程中,也許忽略了UIWindow。因為系統已經幫我們處理了它的相關操作。比如在程式啟動過程中。調用makeKeyAndVisible方法,使整個程式介面可見。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.rootViewController = [self rootViewController]; [self.window makeKeyAndVisible]; return YES;}
但大家常用的建立項目應該是 “Single View Application”, 蘋果幫我們封裝的更徹底了。 連上面的代碼都看不到了。這對於我們理解底層的實現過程是不利的。
在IOS應用中,我們使用UIWindow和UIView來呈現介面。UIWindow並不包含任何預設的內容,但它是被當做UIView的容器,用於放置應用中所有的UIView。從繼承關係來看,UIWindow繼承自UIView,所以UIWIndow除了具有UIView的所有功能外,還增加了一些特有的屬性和方法。
UIWindow的主要作用:1.作為UIView的最頂層容器,包含應用顯示所需要的所有UIView。2.傳遞觸摸訊息和鍵盤事件給UIView(註:關於事件訊息的傳遞,如果有什麼疑問的,請參考我上一節的部落格,請點擊這裡)。
關於系統對UIWindow的使用。通常在一個程式中只會有一個UIWindow,但有些時候我們調用系統的控制項(例如UIAlertView)時,IOS系統為了保證UIAlertView在所有的介面之上,它會臨時建立一個新的UIWindow,通過將其UIWindow的UIWindowLevel設定的更高,讓UIWindow蓋在所有的應用介面之上(熟悉html的朋友應該知道,網上上面的“遮罩效果”,就是通過設定元素的z-index屬性,來控制層級的上下關係,應該是一個道理)。
有時候,我們也希望在應用開發中,將某些介面覆蓋在所有介面最上層。這個時候,我們就可以手工建立一個新的UIWindow。例如,想做一個密碼保護功能,在使用者從應用的任何介面按Home鍵退出,過段時間再從後台切換回來時,顯示一個密碼輸入介面。
Demo介面很簡單,每次啟動應用或者從後台進入應用,都會顯示輸入密碼介面,只有密碼輸入正確,才能使用應用。
大致代碼如下:PasswordInputWindow.h 檔案。 定義一個繼承自UIWindow的子類 PasswordInputWindow, shareInstance 是單例, show方法就是用來顯示輸入密碼介面。
@interface PasswordInputView : UIWindow+ (PasswordInputView *)shareInstance;- (void)show;@end
PasswordInputWindow.m 檔案。
#import "PasswordInputView.h"@interface PasswordInputView()@property (nonatomic,weak) UITextField *textField;@end@implementation PasswordInputView#pragma mark - Singleton+ (PasswordInputView *)shareInstance { static id instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] initWithFrame:[UIScreen mainScreen].bounds]; }); return instance;}#pragma mark - Initilize- (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setup]; } return self;}- (instancetype)initWithCoder:(NSCoder *)decoder { if (self = [super initWithCoder:decoder]) { [self setup]; } return self;}- (void)setup { UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 50, 200, 20)]; label.text = @"請輸入密碼"; [self addSubview:label]; UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 80, 200, 20)]; textField.backgroundColor = [UIColor whiteColor]; textField.secureTextEntry = YES; [self addSubview:textField]; self.textField = textField; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 110, 200, 44)]; [button setBackgroundColor:[UIColor blueColor]]; [button setTitle:@"確定" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [button addTarget:self action:@selector(completeButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:button]; self.backgroundColor = [UIColor yellowColor];}#pragma mark - Common Methods- (void)completeButtonPressed:(UIButton *)button { if ([self.textField.text isEqualToString:@"123456"]) { [self.textField resignFirstResponder]; [self resignKeyWindow]; self.hidden = YES; } else { [self showErrorAlertView]; }}- (void)showErrorAlertView { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"密碼錯誤,請重新輸入" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alertView show];}- (void)show { [self makeKeyWindow]; self.hidden = NO;}@end
1.代碼中我實現了initWithFrame和initWithCoder兩個方法,這樣可以保證,不管使用者是純程式碼還是xib實現的初始化,都沒有問題。2.如果我們建立的UIWindow需要處理鍵盤事件,那就要合理的將其設定為keyWindow。keyWindow是被系統設計用來接受鍵盤和其他非觸摸事件的UIWindow。我們可以通過makeKeyWindow 和 resignKeyWindow 方法來將自己建立的UIWindow執行個體設定成keyWindow。3. 加入以下代碼,就可以保證,程式每次從後台進入的時候,先顯示輸入密碼介面了。
- (void)applicationDidBecomeActive:(UIApplication *)application { [[PasswordInputView shareInstance] show];}