最近比較忙,事也多,這些tips有些亂,沒有進(jìn)行整理,先貼出來(lái),之后會(huì)好好整理,大家多包涵。
文件目錄管理:
Utils:這里放一些與應(yīng)用無(wú)關(guān)的幫助類文件和全局工具類文件
Components:(項(xiàng)目名)這是重頭戲,所有的模塊都會(huì)被放到這里主工程文件
Vendors:這里放一些第三方的類庫(kù),如MagicalRecord / CCUIViewWrapper等等
Models:與數(shù)據(jù)打交道的Model都會(huì)放到這里(數(shù)據(jù),業(yè)務(wù),viewmodel)
Config:應(yīng)用的默認(rèn)設(shè)置文件,plist文件等
模塊粒度劃分:
按需要拆分如果其他地方很少會(huì)單獨(dú)使用到這些實(shí)體,就可以整體作為一個(gè)模塊。當(dāng)然如果將來(lái)其他模塊會(huì)用到其中的某一部分,就需要重新拆分了
xcode:
昨天手賤升級(jí)到iOS10,然后Xcode就得升級(jí)到8......于是各種失效......我也是無(wú)語(yǔ)了
百度到Xcode8注釋快捷鍵的失效解決方法,這里碼一下:
命令運(yùn)行: sudo /usr/libexec/xpccachectl
然后必須重啟電腦后生效
objection:
objection 是一個(gè)輕量級(jí)的依賴注入框架;原理是先定義一個(gè)協(xié)議(protocol),然后通過(guò)objection來(lái)注冊(cè)這個(gè)協(xié)議對(duì)應(yīng)的class(在+(void)load里),需要的時(shí)候,可以獲取該協(xié)議對(duì)應(yīng)的object([injector getObject:@protocol(….Protocol)];)。對(duì)于使用方無(wú)需關(guān)心到底使用的是哪個(gè)Class,反正該有的方法、屬性都有了(在協(xié)議中指定)。這樣就去除了對(duì)某個(gè)特定Class的依賴。也就是通常所說(shuō)的「面向接口編程」;
CopyOnWrite:
讀寫分離技術(shù),讀的時(shí)候讀原來(lái)的對(duì)象,寫的時(shí)候會(huì)復(fù)制一個(gè)原對(duì)象的副本,往新對(duì)象修改,改完之后把指針指向新對(duì)象。優(yōu)點(diǎn):1.減少擴(kuò)容開銷。根據(jù)實(shí)際需要,初始化CopyOnWriteMap的大小,避免寫時(shí)CopyOnWriteMap擴(kuò)容的開銷;2.使用批量添加。因?yàn)槊看翁砑?,容器每次都?huì)進(jìn)行復(fù)制,所以減少添加次數(shù),可以減少容器的復(fù)制次數(shù)。如使用上面代碼里的addBlackList方法; 缺點(diǎn):1.即內(nèi)存占用問(wèn)題;2.數(shù)據(jù)一致性問(wèn)題;
alloc init:
init 還有一個(gè)需要注意的問(wèn)題。某些情況下,init 會(huì)造成 alloc 的原本空間不夠用,而第二次分配內(nèi)存空間。所以下面的寫法是錯(cuò)的
根據(jù)設(shè)計(jì)模式的 Single Responsibility 的設(shè)計(jì)原則,蘋果覺得 alloc 和 init 是做的 2 件不同的事情,把這兩件事情分開放在 2 個(gè)函數(shù)中,對(duì)于程序員更加清楚明了。更詳細(xì)查閱文檔后,我覺得這是由于歷史原因,讓蘋果覺得 alloc 方法過(guò)于復(fù)雜,在歷史上,alloc 不僅僅是分配內(nèi)存,還可以詳細(xì)的指定該內(nèi)存所在的內(nèi)存分區(qū)
@defs 關(guān)鍵字用于返回一個(gè) Objective-C 類的 struct 結(jié)構(gòu),這個(gè) struct 與原 Objective-C 類具有相同的內(nèi)存布局。就象你所知的那樣,Objective-C 類可以理解成由基本的 C struct 加上額外的方法構(gòu)成 struct { @defs( NSObject) }
@compatibility_alias AliasClassName ExistingClassName 用于給一個(gè)類設(shè)置一個(gè)別名
view渲染和內(nèi)存使用:
CALayer 是一個(gè) bitmap 圖象的容器類,當(dāng) UIView 調(diào)用自身的 drawRect 時(shí),CALayer 才會(huì)創(chuàng)建這個(gè) bitmap 圖象類。具體占內(nèi)存的其實(shí)是一個(gè) bitmap 圖象類,CALayer 只占 48bytes, UIView 只占 96bytes。而一個(gè) iPad 的全屏 UIView 的 bitmap 類會(huì)占到 12M 的大??!
在 iOS6 時(shí),當(dāng)系統(tǒng)發(fā)出 MemoryWarning 時(shí),系統(tǒng)會(huì)自動(dòng)回收 bitmap 類。但是不回收 UIView 和 CALayer 類。這樣即回收了大部分內(nèi)存,又能在需要 bitmap 類時(shí),通過(guò)調(diào)用 UIView 的 drawRect: 方法重建
當(dāng)一段內(nèi)存被分配時(shí),它會(huì)被標(biāo)記成 “In use“, 以防止被重復(fù)使用。當(dāng)內(nèi)存被釋放時(shí),這段內(nèi)存會(huì)被標(biāo)記成 “Not in use”,這樣,在有新的內(nèi)存申請(qǐng)時(shí),這塊內(nèi)存就可能被分配給其它變量。CALayer 包括的具體的 bitmap 內(nèi)容的私有成員變量類型為 [CABackingStore](http://blog.spacemanlabs.com/2011/08/calayer-internals-contents/), 當(dāng)收到 MemroyWarning 時(shí),CABackingStore 類型的內(nèi)存區(qū)會(huì)被標(biāo)記成 volatile 類型(這里的 volatile 和 C 以及 Java 語(yǔ)言的 volatile 不是一個(gè)意思),volatile 表示,這塊內(nèi)存可能被再次被原變量重用。這樣,有了上面的優(yōu)化后,當(dāng)收到 Memoy Warning 時(shí),雖然所有的 CALayer 所包含的 bitmap 內(nèi)存都被標(biāo)記成 volatile 了,但是只要這塊內(nèi)存沒有再次被復(fù)用,那么當(dāng)需要重建 bitmap 內(nèi)存時(shí),它就可以直接被復(fù)用,而避免了再次調(diào)用 UIView 的 drawRect: 方法
支付寶的插件機(jī)制(應(yīng)用內(nèi)嵌別的應(yīng)用):
支付寶的插件機(jī)制整體上就是通過(guò) html 和 javascript 方式實(shí)現(xiàn)的,主要的好處是:
跨平臺(tái) (可以同時(shí)用在 iOS 和 Android 客戶端)
省流量(不需要的插件不用下載,插件本地緩存長(zhǎng)期存在不會(huì)過(guò)期,自己管理插件更新邏輯)
更新方便(不用每次提交 AppStore 審核)
壞處如果非要說(shuō)有的話,就是用 javascript 寫 iOS 界面,無(wú)法提供非常炫的 UI 交互以及利用到 iOS 的所有平臺(tái)特性。不過(guò)象支付寶這種工具類應(yīng)用,也不需要很復(fù)雜的 UI 交互效果。
另外教大家一個(gè)小技巧,如果你不確定某個(gè)頁(yè)面是不是 UIWebView 做的,直接在那個(gè)頁(yè)面長(zhǎng)按,如果彈出 “ 拷貝,定義,學(xué)習(xí) “ 這種菜單,那就是確定無(wú)疑是 UIWebView 的界面了。如下圖所示
結(jié)構(gòu)體:
如下 2 個(gè)結(jié)構(gòu)體 SampleA 和 SampleB 在內(nèi)存上是完全一樣的,原因是結(jié)構(gòu)體本身并不帶有任何額外的附加信息
struct SampleA {
int a;
int b;
int c;
};
struct SampleB {
int a;
struct Part1 {
int b;
};
struct Part2 {
int c;
};
};
特殊字體:
使用動(dòng)態(tài)下載中文字體的 API 可以動(dòng)態(tài)地向 iOS 系統(tǒng)中添加字體文件,這些字體文件都是下載到系統(tǒng)的目錄中(目錄是/private/var/mobile/Library/Assets/com_apple_MobileAsset_Font/),所以并不會(huì)造成應(yīng)用體積的增加。并且,由于字體文件是 iOS 系統(tǒng)提供的,也免去了字體使用版權(quán)的問(wèn)題。雖然第一次下載相關(guān)的中文字體需要一些網(wǎng)絡(luò)開銷和下載時(shí)間,但是這些字體文件下載后可以在所有應(yīng)用間共享,所以可以遇見到,隨著該 API 使用的普及,大部分應(yīng)用都不需要提示用戶下載字體,因?yàn)楹芸赡苓@些字體在之前就被其它應(yīng)用下載下來(lái)了
Objective-C對(duì)象模型:
方法的定義列表是一個(gè)名為 methodLists的指針的指針(如下圖所示)。通過(guò)修改該指針指向的指針的值,就可以實(shí)現(xiàn)動(dòng)態(tài)地為某一個(gè)類增加成員方法。這也是Category實(shí)現(xiàn)的原理。同時(shí)也說(shuō)明了為什么Category只可為對(duì)象增加成員方法,卻不能增加成員變量;
系統(tǒng)提供的 KVO 的實(shí)現(xiàn),就利用了動(dòng)態(tài)地修改 isa 指針的值的技術(shù),所以不應(yīng)依賴isa確定所屬類,可能不準(zhǔn)確,而應(yīng)依賴類方法去確定
Objective-C 提供了以下 API 來(lái)動(dòng)態(tài)替換類方法或?qū)嵗椒ǖ膶?shí)現(xiàn):
class_replaceMethod 替換類方法的定義
method_exchangeImplementations 交換 2 個(gè)方法的實(shí)現(xiàn)(內(nèi)部實(shí)現(xiàn)相當(dāng)于調(diào)用了 2 次method_setImplementation方法)
method_setImplementation 設(shè)置 1 個(gè)方法的實(shí)現(xiàn)
這 3 個(gè)方法有一些細(xì)微的差別,給大家介紹如下:
class_replaceMethod在蘋果的文檔(如下圖所示)中能看到,它有兩種不同的行為。當(dāng)類中沒有想替換的原方法時(shí),該方法會(huì)調(diào)用class_addMethod來(lái)為該類增加一個(gè)新方法,也因?yàn)槿绱耍琧lass_replaceMethod在調(diào)用時(shí)需要傳入types參數(shù),而method_exchangeImplementations和method_setImplementation卻不需要
initWithFrame:
用[UIView new]或者[[UIView alloc] init]都會(huì)調(diào)用initWithFrame這個(gè)函數(shù)(有些UIView的子類有特殊情況,比如UITableViewCell,懷疑apple對(duì)其做過(guò)特殊處理
響應(yīng)者鏈:
響應(yīng)者樹的構(gòu)造過(guò)程是在ViewDidLoad周期中來(lái)完成的,能夠在viewDidAppear:方法中調(diào)用起效
view在什么情況下能夠變成第一響應(yīng)者?條件是什么?
只要繼承自UIResponder的子類都可使以成為第一響應(yīng)者的,但是除了UITextField,必須在實(shí)現(xiàn)文件中覆蓋canBecomeFirstResponder方法,如果按鈕的target是設(shè)置為nil的,所以系統(tǒng)將去尋找當(dāng)前第一響應(yīng)者,如果第一響應(yīng)者有pressPrint這個(gè)方法,那么他會(huì)調(diào)用它的pressPrint方法。而現(xiàn)在viewD中是實(shí)現(xiàn)了此方法
UITouch事件和響應(yīng)者鏈走的不是同一套機(jī)制,如果UITouch事件響應(yīng)了手勢(shì)就不再響應(yīng)UIEvent事件;或者 UIButton 上加UIView, 因?yàn)椴皇亲咄惶讬C(jī)制,所以會(huì)不響應(yīng)UIEvent事件;(如果藥響應(yīng),可以重寫最上層view的 hittest 返回需要點(diǎn)擊的button為 hitest 響應(yīng)的對(duì)象(穿透原理))
優(yōu)化:
處理圖片時(shí),你也可以讓GPU為你工作來(lái)代替使用Core Graphics。使用Core Image,你不必用CPU做任何的工作就可以在圖片上建立復(fù)雜的效果。你可以直接在OpenGL上下文上直接渲染,所有的工作都在GPU上完成
重寫drawRect:,默認(rèn)的模式是將內(nèi)容縮放以填充視圖的范圍,并且當(dāng)視圖的frame改變時(shí)并不會(huì)重新繪制
如果你使用的層引發(fā)了離屏渲染,那么你最好避免這種方式。增加遮罩,設(shè)置圓角,設(shè)置陰影都造成離屏渲染。(動(dòng)畫也會(huì),但是動(dòng)畫中可以提升性能)
當(dāng)一個(gè)層上面的所有像素和屏幕上面的像素完美對(duì)應(yīng),我們就說(shuō)這個(gè)層是像素對(duì)齊的。主要有2個(gè)原因?qū)е驴赡懿粚?duì)齊。第一個(gè)是放大縮?。划?dāng)放大或是縮小是,紋理的像素和屏幕像素不對(duì)齊。另一個(gè)原因是當(dāng)紋理的起點(diǎn)不在一個(gè)像素邊界上。
這2種情況,GPU不得不做額外的計(jì)算。這個(gè)需要從源紋理中混合很多像素來(lái)創(chuàng)建一個(gè)像素用來(lái)合成。當(dāng)所有像素對(duì)齊時(shí),GPU就可以少做很多工作
NSNumber:
所以給一個(gè)weak對(duì)象賦值,它并不會(huì)馬上釋放,而是會(huì)放到autorelease pool中,與autorelease pool一起釋放
Tagged Pointer專門用來(lái)存儲(chǔ)小的對(duì)象,例如NSNumber和NSDate
Tagged Pointer指針的值不再是地址了,而是真正的值(其實(shí)是將值存在指針內(nèi),即指針也就是值)。所以,實(shí)際上它不再是一個(gè)對(duì)象了,它只是一個(gè)披著對(duì)象皮的普通變量而已!所以,它的內(nèi)存并不存儲(chǔ)在堆中,也不需要malloc,free。
在內(nèi)存讀取上有著3倍的效率(以前是尋址->發(fā)消息->獲取值,現(xiàn)在直接獲取值),創(chuàng)建時(shí)比以前快106倍
load:
所以庫(kù)的初始化順序可以如下:
- 初始化我們引用的庫(kù)
- 執(zhí)行我們自己庫(kù)的Objective-C的load函數(shù)
- 執(zhí)行C++和C的static初始化變量
- 初始化引用我們庫(kù)的其他庫(kù)
在我們的編寫的庫(kù)中,會(huì)有很多類重寫load函數(shù),他們之間的執(zhí)行順序是不確定的。
當(dāng)父類和子類都實(shí)現(xiàn)load函數(shù)時(shí),父類的load函數(shù)會(huì)被先執(zhí)行。load函數(shù)是系統(tǒng)自動(dòng)加載的,因此不需要調(diào)用父類的load函數(shù),否則父類的load函數(shù)會(huì)多次執(zhí)行。
在Category中寫load函數(shù)是不會(huì)替換原始類中的load函數(shù)的,原始類和Category中的load函數(shù)都會(huì)被執(zhí)行,原始類的load會(huì)先被執(zhí)行,再執(zhí)行Category中的load函數(shù)。當(dāng)有多個(gè)Category都實(shí)現(xiàn)了load函數(shù),這幾個(gè)load函數(shù)執(zhí)行順序不確定
如果類包含繼承關(guān)系,父類的initialize函數(shù)會(huì)比子類先執(zhí)行。由于是系統(tǒng)自動(dòng)調(diào)用,也不需要顯式的調(diào)用父類的initialize,否則父類的initialize會(huì)被多次執(zhí)行。
假如這個(gè)類放到代碼中,而這段代碼并沒有被執(zhí)行,這個(gè)函數(shù)是不會(huì)被執(zhí)行的
但是假如我們是修改系統(tǒng)的類,一般會(huì)通過(guò)添加Category來(lái)添加功能,但是Category中如果修改initialize會(huì)導(dǎo)致原生的intialize不會(huì)執(zhí)行,所以放在load中會(huì)比較妥當(dāng)
bridge:
如之前提到的,MRC 下的 Toll-Free Bridging 因?yàn)椴簧婕皟?nèi)存管理的轉(zhuǎn)移,相互之間可以直接交換使用:
NSString *nsStr = (NSString *)cfStr;CFStringRef cfStr = (CFStringRef)nsStr;// 調(diào)用函數(shù)或者方法NSUInteger length = [(NSString *)cfStr length];NSUInteger length = CFStringGetLength((CFStringRef)nsStr);// releaseCFRelease((CFStringRef)nsStr);[(NSString *)cfStr release];
而在 ARC 下,事情就會(huì)變得復(fù)雜一些,因?yàn)?ARC 能夠管理 Objective-C 對(duì)象的內(nèi)存,卻不能管理 CF 對(duì)象,CF 對(duì)象依然需要我們手動(dòng)管理內(nèi)存。在 CF 和 ObjC 之間 bridge 對(duì)象的時(shí)候,問(wèn)題就出現(xiàn)了,編譯器不知道該如何處理這個(gè)同時(shí)有 ObjC 指針和 CFTypeRef 指向的對(duì)象。
如何實(shí)現(xiàn)父類的私有方法子類可以訪問(wèn):
這時(shí)候,我們需要使用__bridge (不做任何處理,指向同一對(duì)象,由轉(zhuǎn)化前的對(duì)象管理內(nèi)存,后來(lái)的對(duì)象相當(dāng)于一個(gè)弱指針), __bridge_retained(做一次retain,共同管理內(nèi)存), __bridge_transfer (轉(zhuǎn)化,由轉(zhuǎn)化后的對(duì)象管理內(nèi)存)
有Father類和Son類,繼承關(guān)系,可以考慮建一個(gè)如FatherPrivate.h的私有header:
<colgroup><col style="width: 603px;"></colgroup>
|
// FatherPrivate.h
@interface Father ()
@property (nonatomic, copy) NSString *privateThingSonNeed;
- (void)privateMethodNeedsSonOverride;
@end
|
同時(shí)在Father.m和Son.m中同時(shí)import這個(gè)私有header,這樣,F(xiàn)ather和Son內(nèi)部對(duì)于定義的屬性和方法都是透明的,而對(duì)外部是隱藏的(因?yàn)閮蓚€(gè)類的header中都沒有import這個(gè)私有header
2D繪圖:
這里我們發(fā)現(xiàn),UIKit的代碼并沒有傳遞context。這是因?yàn)閁IKit或AppKit的context是隱形的。UIKit和UIKit維護(hù)著一個(gè)context棧。這些UIKit的方法始終在最上面的context繪制。你可以使用UIGraphicsPushContext()和 UIGraphicsPopContext()來(lái)push和pop對(duì)應(yīng)的context。
BDD和基于bdd的測(cè)試框架kiwi:
一個(gè)典型的BDD的測(cè)試用例包活完整的三段式上下文,測(cè)試大多可以翻譯為Given..When..Then的格式,即在一個(gè)上下文下,當(dāng)給予一個(gè)的條件時(shí),應(yīng)該有的行為或特性;
可變參數(shù)的函數(shù):
-(id)initWithTitle:(NSString)title message:(NSString)message clickedBlock:(void (^)(CYAlertView *alertView, BOOL cancelled, NSInteger buttonIndex))clickedBlock cancelButtonTitle:(NSString )cancelButtonTitle otherButtonTitles:(NSString)otherButtonTitles,…NS_REQUIRES_NIL_TERMINATION; (可變參數(shù)列表)
collectionView自定義動(dòng)畫:
給系統(tǒng)方法返回初始布局和終止布局,系統(tǒng)會(huì)自動(dòng)過(guò)度,如果需要區(qū)分狀態(tài),只要使用系統(tǒng)的枚舉來(lái)記錄判斷當(dāng)前出去插入,刪除,或者轉(zhuǎn)場(chǎng)等等狀態(tài)予以區(qū)分即可
繪圖:
使用UiKit,你只能在當(dāng)前上下文中繪圖,所以如果你當(dāng)前處于UIGraphicsBeginImageContextWithOptions函數(shù)或drawRect:方法中,你就可以直接使用UIKit提供的方法進(jìn)行繪圖。如果你持有一個(gè)context:參數(shù),那么使用UIKit提供的方法之前,必須將該上下文參數(shù)轉(zhuǎn)化為當(dāng)前上下文。幸運(yùn)的是,調(diào)用UIGraphicsPushContext 函數(shù)可以方便的將context:參數(shù)轉(zhuǎn)化為當(dāng)前上下文,記住最后別忘了調(diào)用UIGraphicsPopContext函數(shù)恢復(fù)上下文環(huán)境
運(yùn)行時(shí):
我們經(jīng)常在方法中使用self關(guān)鍵字來(lái)引用實(shí)例本身,但從沒有想過(guò)為什么self就能取到調(diào)用當(dāng)前方法的對(duì)象吧。其實(shí)self的內(nèi)容是在方法運(yùn)行時(shí)被偷偷的動(dòng)態(tài)傳入的。
當(dāng)objc_msgSend找到方法對(duì)應(yīng)的實(shí)現(xiàn)時(shí),它將直接調(diào)用該方法實(shí)現(xiàn),并將消息中所有的參數(shù)都傳遞給方法實(shí)現(xiàn),同時(shí),它還將傳遞兩個(gè)隱藏的參數(shù):
1.接收消息的對(duì)象(也就是self指向的內(nèi)容)
2.方法選擇器(_cmd指向的內(nèi)容)
[super class]等價(jià)于[self class]
盡管轉(zhuǎn)發(fā)很像繼承,但是NSObject類不會(huì)將兩者混淆。像respondsToSelector: 和 isKindOfClass:這類方法只會(huì)考慮繼承體系,不會(huì)考慮轉(zhuǎn)發(fā)鏈。比如上圖中一個(gè)Warrior對(duì)象如果被問(wèn)到是否能響應(yīng)negotiate消息:結(jié)果是NO,因?yàn)樗m然能夠接受negotiate消息而不報(bào)錯(cuò),是因?yàn)樗哭D(zhuǎn)發(fā)消息給Diplomat類來(lái)響應(yīng)消息而不是實(shí)現(xiàn)了Diplomat方法;
1)、category會(huì)在編譯時(shí)將方法和屬性鏈接到類的方法和屬性列表中,category的方法沒有“完全替換掉”原來(lái)類已經(jīng)有的方法,也就是說(shuō)如果category和原來(lái)類都有methodA,那么category附加完成之后,類的方法列表里會(huì)有兩個(gè)methodA
2)、category的方法被放到了新方法列表的前面,而原來(lái)類的方法被放到了新方法列表的后面,這也就是我們平常所說(shuō)的category的方法會(huì)“覆蓋”掉原來(lái)類的同名方法,這是因?yàn)檫\(yùn)行時(shí)在查找方法的時(shí)候是順著方法列表的順序查找的,它只要一找到對(duì)應(yīng)名字的方法,就會(huì)罷休_,殊不知后面可能還有一樣名字的方法。
3)、附加category到類的工作會(huì)先于+load方法的執(zhí)行,所以可以在類的+load方法中調(diào)用category方法。
4)、AssociationsManager里面是由一個(gè)靜態(tài)AssociationsHashMap 來(lái)存儲(chǔ)所有的關(guān)聯(lián)對(duì)象的。這相當(dāng)于把所有對(duì)象的關(guān)聯(lián)對(duì)象都存在一個(gè)全局map里面。而map的的key是這個(gè)對(duì)象的指針地址(任意兩個(gè)不同對(duì)象的指針地址一定是不同的),而這個(gè)map的value又是另外一個(gè)AssociationsHashMap,里面保存了關(guān)聯(lián)對(duì)象的kv對(duì)。而在對(duì)象的銷毀邏輯里面runtime的銷毀對(duì)象函數(shù)objc_destructInstance里面會(huì)判斷這個(gè)對(duì)象有沒有關(guān)聯(lián)對(duì)象,如果有,會(huì)調(diào)用_object_remove_assocations做關(guān)聯(lián)對(duì)象的清理工作
靜態(tài)庫(kù), 動(dòng)態(tài)鏈接庫(kù),動(dòng)態(tài)加載庫(kù):
沙盒目錄及使用:
[NSUserDefaults standardUserDefaults] Library下的Preference,使用系統(tǒng)的plist文件;如果想要新建一個(gè)plist文件可以:
[[NSUserDefaults alloc]initWithSuiteName:@"gxw”]; 創(chuàng)建一個(gè)叫 gxw.plist的文件,如果已有就直接獲取,沒有就重新創(chuàng)建一個(gè);
UIWindow:
UIWindow有 UIWindowLevel 屬性,是一個(gè) cgfloat 類型 包含三個(gè)枚舉 normal = 0.0,statusbar = 1000.0,alert = 2000.0 當(dāng)前keywindow隊(duì)列中l(wèi)evel值越大的window顯示在最上面; 系統(tǒng)默認(rèn)的是 normal = 0.0; statusbar狀態(tài)欄的window 是 1000.0; 系統(tǒng) alert 的是1996.0 左右; 設(shè)置 key 用來(lái)接收鍵盤輸入等非觸摸事件;如果想實(shí)現(xiàn)一些遮蓋狀態(tài)欄的彈窗可以利用 UIWindowLevel 實(shí)現(xiàn);
編譯警告:
在Build Phases中的 Compile Sources中每個(gè)文件加入 -w 可以忽略掉該文件的編譯警告, 加入 -Wno-unused-variable 可以忽略未使用的變量名警官
對(duì)象的轉(zhuǎn)換:
為什么要在主線程刷新UI:(自線程的UI操作需要在自線程生命周期結(jié)束后執(zhí)行,實(shí)際上也是返回給主線程執(zhí)行)
1.(google的一套UI刷新規(guī)則)多線程操作UI控件,由于移動(dòng)設(shè)備UI控件多,復(fù)雜,還有動(dòng)畫,交互等等復(fù)雜的邏輯容易出錯(cuò),且移動(dòng)設(shè)備設(shè)計(jì)之初內(nèi)存小,CPU數(shù)量和性能原因,所以把UI刷新統(tǒng)一放在UI線程執(zhí)行,簡(jiǎn)化了邏輯也符合移動(dòng)端較強(qiáng)UI展示的需要,也方便管理提高UI的使用效率;
2.如果能解決多線程的弊端確實(shí)可以提升效率,但是與其對(duì)規(guī)則推倒重來(lái)使用復(fù)雜的規(guī)則不如專注于設(shè)備硬件性能提升上;
3.自線程執(zhí)行耗時(shí)操作,主線程執(zhí)行重量級(jí)操作;