開發中常見問題集錦

這篇文章是專門用來記錄開發中一些常見的BUG以及經常使用的零碎知識點,我會隔一段時間更新內容數組

1.重複調用2次loadView和viewDidLoad

最好不要在UIViewController的loadView方法中改變狀態欄的可視性(好比狀態欄由顯示變爲隱藏、或者由隱藏變爲顯示),由於會致使重複調用2次loadView和viewDidLoad方法app

假設狀態欄原本是處於顯示狀態的:ide

下面的是錯誤代碼: this

複製代碼
 1 - (void)loadView {  2 NSLog(@"loadView");  3 // 隱藏狀態欄  4 [UIApplication sharedApplication].statusBarHidden = YES;  5  6 // .... 建立UIView  7 self.view = [[[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds] autorelease];  8 self.view.backgroundColor = [UIColor grayColor];  9  } 10 11 - (void)viewDidLoad { 12  [super viewDidLoad]; 13 NSLog(@"viewDidLoad"); 14 }
複製代碼

運行效果:spa

打印信息:3d

1 2013-02-26 00:51:36.152 weibo[2251:c07] loadView 2 2013-02-26 00:51:36.153 weibo[2251:c07] loadView 3 2013-02-26 00:51:36.153 weibo[2251:c07] viewDidLoad 4 2013-02-26 00:51:36.154 weibo[2251:c07] viewDidLoad

雖然運行效果是對的,可是系統連續調用了2次loadView和viewDidLoad方法,致使建立了2次UIView,形成了沒必要要的開銷。code

緣由分析:對象

狀態欄由顯示變爲隱藏,意味着屏幕的可用高度變長了,UIViewController的UIView的高度也要從新調整,所以系統會從新調用loadView方法建立UIView,建立完畢後再次調用viewDidLoad方法。blog

 

2.按鈕沒法點擊

若是在UIImageView中添加了一個按鈕,你會發如今默認狀況下這個按鈕是沒法被點擊的,須要設置UIImageView的userInteractionEnabled爲YES:繼承

imageView.userInteractionEnabled = YES;

設置爲YES後,UIImageView內部的按鈕就能夠被點擊了

緣由分析:

• 當用戶點擊屏幕時,會產生一個觸摸事件,系統會將該事件加入到一個由UIApplication管理的事件隊列中

• UIApplication會從事件隊列中取出最前面的事件進行分發以便處理,一般,先發送事件給應用程序的主窗口(UIWindow)

• 主窗口會調用hitTest:withEvent:方法在視圖(UIView)層次結構中找到一個最合適的UIView來處理觸摸事件

(hitTest:withEvent:實際上是UIView的一個方法,UIWindow繼承自UIView,所以主窗口UIWindow也是屬於視圖的一種)

hitTest:withEvent:方法大體處理流程是這樣的:

首先調用當前視圖的pointInside:withEvent:方法判斷觸摸點是否在當前視圖內:

▶ 若pointInside:withEvent:方法返回NO,說明觸摸點不在當前視圖內,則當前視圖的hitTest:withEvent:返回nil

▶ 若pointInside:withEvent:方法返回YES,說明觸摸點在當前視圖內,則遍歷當前視圖的全部子視圖(subviews),調用子視圖的hitTest:withEvent:方法重複前面的步驟,子視圖的遍歷順序是從top到bottom,即從subviews數組的末尾向前遍歷,直到有子視圖的hitTest:withEvent:方法返回非空對象或者所有子視圖遍歷完畢:

▷ 若第一次有子視圖的hitTest:withEvent:方法返回非空對象,則當前視圖的hitTest:withEvent:方法就返回此對象,處理結束

▷ 若全部子視圖的hitTest:withEvent:方法都返回nil,則當前視圖的hitTest:withEvent:方法返回當前視圖自身(self)

最終,這個觸摸事件交給主窗口的hitTest:withEvent:方法返回的視圖對象去處理

我大體畫了個iOS觸摸事件分發的原理圖:

• hitTest:withEvent:方法會忽略如下視圖:

1> 隱藏(hidden=YES)的視圖

2> 禁止用戶操做(userInteractionEnabled=NO)的視圖

3> alpha<0.01的視圖

4> 若是一個子視圖的區域超過父視圖的區域(若是父視圖的clipsToBounds屬性爲NO,超過父視圖區域的子視圖內容也會顯示),那麼正常狀況下在父 視圖區域外的觸摸操做不會被識別,由於父視圖的pointInside:withEvent:方法會返回NO,這樣就不會繼續向下遍歷子視圖了。固然,也 能夠重寫pointInside:withEvent:方法來處理這種

綜上所述可得:若是父視圖的userInteractionEnabled=NO,觸摸事件不會繼續往下傳遞給子視圖,因此子視圖永遠沒法處理觸摸事件。而UIImageView在默認狀況下的userInteractionEnabled就是NO。

 

3.@2x和-568h@2x

於iOS設備的屏幕分辨率不盡相同,有大有小,那麼在不一樣設備中 顯示同一張圖片,可能會形成圖片被拉伸、變形,嚴重影響用戶體驗。

爲了讓圖片在不一樣設備中都能獲得很好的顯示效果,同一類圖片咱們通常會準備3種版本,好比iOS程序在啓動時會全屏顯示的Default.png圖片:

(Retina即視網膜屏幕)

• Default.png(圖片尺寸爲320x480):顯示在非Retina-3.5英寸屏幕上(iPhone3G\iPhone3GS,屏幕分辨率爲320x480)

• Default@2x.png(圖片尺寸爲640x960):顯示在Retina-3.5英寸屏幕上(iPhone4\iPhone4s,屏幕分辨爲640x960)

• Default-568h@2x.png(圖片尺寸爲640x1136):顯示在Retina-4.0英寸屏幕上(iPhone5,屏幕分辨率爲640x1136)

 

4.啓動app時全屏顯示Default.png

大部分app在啓動過程當中全屏顯示一張背景圖片,好比新浪微博會顯示這張:

想在iOS中實現這種效果,毫無壓力,很是地簡單,把須要全屏顯示的圖片命名爲Default.png便可,在iOS app啓動時默認會去加載並全屏顯示Default.png。

也可以用其餘名稱來命名圖片,在Info.plist配置一下便可:

配置事後,app啓動時就會去加載並全屏顯示lufy.png

在默認情況下,app顯示Default.png時並不是真正的"全屏顯示",由於頂部的狀態欄並無被隱藏,好比下面的效果:

大部分狀況下,咱們都想隱藏狀態欄,讓Default.png真正全屏顯示。

說到這裏,可能有人立刻就想到了一種辦法:在AppDelegate的application:didFinishLaunchingWithOptions:方法中添加以下代碼:

[UIApplication sharedApplication].statusBarHidden = YES; 

我只能說你的思路是對的,但實際上達不到想要的效果,你會發現顯示Default.png時狀態欄仍是存在的,等Default.png顯示完畢後,狀態欄才被隱藏。

先解釋下爲何這種方法不可行,其實緣由很簡單:

1> Default.png是在app啓動過程當中加載的,並非在app啓動完畢後再加載的

2> AppDelegate的application:didFinishLaunchingWithOptions:方法是在app啓動完畢後才調用的

下面說一下解決方案,在Info.plist中增長一個配置便可:

這裏的YES表示在app初始化(啓動)的時候就隱藏狀態欄。

固然,在Default.png顯示完畢後狀態欄仍是隱藏的。若是想從新顯示狀態欄,補上下面代碼便可:

[UIApplication sharedApplication].statusBarHidden = NO; 
相關文章
相關標籤/搜索