詳解iOS設計中的UIWindow使用
每一個IOS程序都有一個UIWindow,在我們通過模板簡歷工程的時候,xcode會自動幫我們生成一個window,然后讓它變成keyWindow并顯示出來。這一切都來的那么自然,以至于我們大部分時候都忽略了自己也是可以創(chuàng)建UIWindow對象。
通常在我們需要自定義UIAlertView的時候(IOS 5.0以前AlertView的背景樣式等都不能換)我們可以使用UIWindow來實現(xiàn)(設置windowLevel為Alert級別),網(wǎng)上有很多例子,這里就不詳細說了。
一、UIWindowLevel
我們都知道UIWindow有三個層級,分別是Normal,StatusBar,Alert。打印輸出他們?nèi)齻€這三個層級的值我們發(fā)現(xiàn)從左到右依次是0,1000,2000,也就是說Normal級別是最低的,StatusBar處于中等水平,Alert級別最高。而通常我們的程序的界面都是處于Normal這個級別上的,系統(tǒng)頂部的狀態(tài)欄應該是處于StatusBar級別,UIActionSheet和UIAlertView這些通常都是用來中斷正常流程,提醒用戶等操作,因此位于Alert級別。
上一篇文章中我也提到了一個猜想,既然三個級別的值之間相差1000,而且我們細心的話查看UIWindow的頭文件就會發(fā)現(xiàn)有一個實例變量_windowSublevel,那我們就可以定義很多中間級別的Window。例如可以自定義比系統(tǒng)UIAlertView級別低一點兒的window。于是寫了一個小demo,通過打印發(fā)現(xiàn)系統(tǒng)的UIAlertView的級別是1996,而與此同時UIActionSheet的級別是2001,這樣也驗證了subLevel的確存在。
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Alert View"
message:@"Hello Wolrd, i'm AlertView!!!"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:@"Cancel", nil];
[alertView show];
[alertView release];
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"ActionSheet"
delegate:nil
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Don't do that!"
otherButtonTitles:@"Hello Wolrd", nil];
[actionSheet showInView:self.view];
[actionSheet release];
下面是程序運行截圖:

根據(jù)window顯示級別優(yōu)先的原則,級別高的會顯示在上面,級別低的在下面,我們程序正常顯示的view位于最底層,至于具體怎樣獲取UIAlertView和UIActionSheet的level,我會在下面第二部分keyWindow中介紹并給出相應的代碼。
UIWindow在顯示的時候會根據(jù)UIWindowLevel進行排序的,即Level高的將排在所有Level比他低的層級的前面。下面我們來看UIWindowLevel的定義:
const UIWindowLevel UIWindowLevelNormal;
const UIWindowLevel UIWindowLevelAlert;
const UIWindowLevel UIWindowLevelStatusBar;
typedef CGFloat UIWindowLevel;
IOS系統(tǒng)中定義了三個window層級,其中每一個層級又可以分好多子層級(從UIWindow的頭文件中可以看到成員變量CGFloat _windowSublevel;),不過系統(tǒng)并沒有把則個屬性開出來。UIWindow的默認級別是UIWindowLevelNormal,我們打印輸出這三個level的值分別如下:
2012-03-27 22:46:08.752 UIViewSample[395:f803] Normal window level: 0.000000 2012-03-27 22:46:08.754 UIViewSample[395:f803] Alert window level: 2000.000000 2012-03-27 22:46:08.755 UIViewSample[395:f803] Status window level: 1000.000000
這樣印證了他們級別的高低順序從小到大為Normal < StatusBar < Alert,下面請看小的測試代碼:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.window.backgroundColor = [UIColor yellowColor];
[self.window makeKeyAndVisible];
UIWindow *normalWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
normalWindow.backgroundColor = [UIColor blueColor];
normalWindow.windowLevel = UIWindowLevelNormal;
[normalWindow makeKeyAndVisible];
CGRect windowRect = CGRectMake(50,
50,
[[UIScreen mainScreen] bounds].size.width - 100,
[[UIScreen mainScreen] bounds].size.height - 100);
UIWindow *alertLevelWindow = [[UIWindow alloc] initWithFrame:windowRect];
alertLevelWindow.windowLevel = UIWindowLevelAlert;
alertLevelWindow.backgroundColor = [UIColor redColor];
[alertLevelWindow makeKeyAndVisible];
UIWindow *statusLevelWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 50, 320, 20)];
statusLevelWindow.windowLevel = UIWindowLevelStatusBar;
statusLevelWindow.backgroundColor = [UIColor blackColor];
[statusLevelWindow makeKeyAndVisible];
NSLog(@"Normal window level: %f", UIWindowLevelNormal);
NSLog(@"Alert window level: %f", UIWindowLevelAlert);
NSLog(@"Status window level: %f", UIWindowLevelStatusBar);
return YES;
}
運行結果如下圖:

我們可以注意到兩點:
1)我們生成的normalWindow雖然是在第一個默認的window之后調(diào)用makeKeyAndVisible,但是仍然沒有顯示出來。這說明當Level層級相同的時候,只有第一個設置為KeyWindow的顯示出來,后面同級的再設置KeyWindow也不會顯示。
2)statusLevelWindow在alertLevelWindow之后調(diào)用makeKeyAndVisible,仍然只是顯示在alertLevelWindow的下方。這說明UIWindow在顯示的時候是不管KeyWindow是誰,都是Level優(yōu)先的,即Level最高的始終顯示在最前面。
二、KeyWindow
什么是keyWindow,官方文檔中是這樣解釋的"The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window." 翻譯過來就是說,keyWindow是指定的用來接收鍵盤以及非觸摸類的消息,而且程序中每一個時刻只能有一個window是keyWindow。
下面我們寫個簡單的例子看看非keyWindow能不能接受鍵盤消息和觸摸消息,程序中我們在view中添加一個UITextField,然后新建一個alert級別的window,然后通過makeKeyAndVisible讓它變成keyWindow并顯示出來。代碼如下:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[SvUIWindowViewController alloc] initWithNibName:@"SvUIWindowViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
UIWindow *window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 80, 320, 320)];
window1.backgroundColor = [UIColor redColor];
window1.windowLevel = UIWindowLevelAlert;
[window1 makeKeyAndVisible];
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self registerObserver];
// add a textfield
UITextField *filed = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 60)];
filed.placeholder = @"Input something here";
filed.clearsOnBeginEditing = YES;
filed.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:filed];
[filed release];
}
運行截圖如下:
從圖中可以看出,雖然我們自己新建了一個然后設置為keyWindow并顯示,但是點擊程序中默認window上添加的textField還是可以喚出鍵盤,而且還可以正常接受鍵盤輸入,只是鍵盤被擋住了,說明非keyWindow也是可以接受鍵盤消息,這一點和文檔上說的不太一樣。
觀察UIWindow的文檔,我們可以發(fā)現(xiàn)里面有四個關于window變化的通知:
UIWindowDidBecomeVisibleNotification UIWindowDidBecomeHiddenNotification UIWindowDidBecomeKeyNotification UIWindowDidResignKeyNotification
這四個通知對象中的object都代表當前已顯示(隱藏),已變成keyWindow(非keyWindow)的window對象,其中的userInfo則是空的。于是我們可以注冊這個四個消息,再打印信息來觀察keyWindow的變化以及window的顯示,隱藏的變動。
代碼如下:
根據(jù)打印的信息我們可以看出流程如下:
1、程序默認的window先顯示出來
2、默認的window再變成keyWindow
3、AlertView的window顯示出來
4、默認的window變成非keyWindow
5、最終AlertView的window變成keyWindow
總體來說就是“要想當老大(keyWindow),先從小弟(非keyWindow)開始混起” 而且根據(jù)打印的信息我們同事可以知道默認的window的level是0,即normal級別;AlertView的window的level是1996,比Alert級別稍微低了一點兒。
b、當我們打開viewDidAppear中“[self presentActionSheet];”的時候,控制臺輸出如下:
keyWindow的變化和window的顯示和上面的流程一樣,同時我們可以看出ActionSheet的window的level是2001。
c、接著上一步,我們點擊彈出ActionSheet的cancel的時候,控制臺輸出如下:
我們看出流程如下:
1、首先ActionSheet的window變成非keyWindow
2、程序默認的window變成keyWindow
3、ActionSheet的window在隱藏掉
總體就是“想隱居幕后可以,但得先交出權利”。
- WMI獲取硬件信息封裝函數(shù)方法(聯(lián)想臺式機出廠編號 CPUID BIOS序列號 硬盤信息 顯卡信息 MAC地址)
- IOS開發(fā)代碼分享之設置UISearchBar的背景顏色
- IOS中UIWebView加載Loading的實現(xiàn)方法
- iOS開發(fā)之使用Storyboard預覽UI在不同屏幕上的運行效果
- iOS - UIButton(UIEdgeInsets)/設置button上的文字和圖片上下垂直居中對齊
- iOS9 系統(tǒng)分享調(diào)用之UIActivityViewController
- iOS開發(fā)中UIDatePicker控件的使用方法簡介
- iOS開發(fā)中使用UILabel設置字體的相關技巧小結
- IOS UI學習教程之設置UITextField各種屬性
相關文章
iOS實現(xiàn)漸變按鈕Gradient Button的方法示例
這篇文章主要給大家介紹了關于iOS實現(xiàn)漸變按鈕Gradient Button的相關資料,文中通過示例代碼介紹的非常詳細,對各位iOS開發(fā)者們具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-08-08IOS網(wǎng)絡請求之AFNetWorking 3.x 使用詳情
本篇文章主要介紹了IOS網(wǎng)絡請求之AFNetWorking 3.x 使用詳情,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02iOS9 系統(tǒng)分享調(diào)用之UIActivityViewController
UIActivityViewController類是一個標準的view controller,通個使用這個controller,你的應用程序就可以提供各種服務。本文給大家介紹iOS9 系統(tǒng)分享調(diào)用之UIActivityViewController,感興趣的朋友一起學習吧2015-11-11