iOS知識大全
iOS知識點大全:
一.Objc三大特性1.封裝2.繼承3.多態
1> 什麽是多態
多態:不同對象以自己的方式響應相同的消息的能力叫做多態。
由於每個類都屬於該類的名字空間,這使得多態稱為可能。類定義中的名字和類定義外的名字並不會沖突。類的實例變量和類方法有如下特點:
- 和C語言中結構體中的數據成員一樣,類的實例變量也位於該類獨有的名字空間。
- 類方法也同樣位於該類獨有的名字空間。與C語言中的方法名不同,類的方法名並不是一個全局符號。一個類中的方法名不會和其他類中同樣的方法名沖突。兩個完全不同的類可以實現同一個方法。
方法名是對象接口的一部分。對象收到的消息的名字就是調用的方法的名字。因為不同的對象可以有同名的方法,所以對象必須能理解消息的含義。同樣的消息發給不同的對象,導致的操作並不相同。
多態的主要好處就是簡化了編程接口。它容許在類和類之間重用一些習慣性的命名,而不用為每一個新加的函數命名一個新名字。這樣,編程接口就是一些抽象的行為的集合,從而和實現接口的類區分開來。
Objective-C支持方法名的多態,但不支持參數和操作符的多態。
2> OC中如何實現多態
在Objective-C中是通過一個叫做selector的選取器實現的。在Objective-C中,selector有兩個意思, 當用在給對象的源碼消息時,用來指方法的名字。它也指那個在源碼編譯後代替方法名的唯一的標識符。 編譯後的選擇器的類型是SEL有同樣名字的方法、也有同樣的選擇器。你可以使用選擇器來調用一個對象的方法。
選取器有以下特點:
* 所有同名的方法擁有同樣的選取器
* 所有的選取器都是不一樣的
(1) SEL和@selector
選擇器的類型是 SEL。@selector指示符用來引用選擇器,返回類型是SEL。
例如:
SEL responseSEL;
responseSEL = @selector(loadDataForTableView:);
可以通過字符串來得到選取器,例如:
responseSEL = NSSelectorFromString(@"loadDataForTableView:");
也可以通過反向轉換,得到方法名,例如:
NSString *methodName = NSStringFromSelector(responseSEL);
(2) 方法和選取器
選取器確定的是方法名,而不是方法實現。這是多態性和動態綁定的基礎,它使得向不同類對象發送相同的消息成為現實;否則,發送 消息和標準C中調用方法就沒有區別,也就不可能支持多態性和動態綁定。
另外,同一個類的同名類方法和實例方法擁有相同的選取器。
(3) 方法返回值和參數類型
消息機制通過選取器找到方法的返回值類型和參數類型,因此,動態綁定(例:向id定義的對象發送消息)需要同名方法的實現擁有相 同返回值類型和相同的參數類型;否則,運行時可能出現找不到對應方法的錯誤。
有一個例外,雖然同名類方法和實例方法擁有相同的選取器,但是它們可以有不同的參數類型和返回值類型。
3> 動態綁定
二.類和對象
1.category
1> 分類拓展協議中哪些可以聲明屬性?
都可以,但分類和協議創建的屬性只相當於方法,但是內部沒有對成員變量的操作(無法創建成員變量),拓展可以
代理中聲明屬性,沒有實際創建成員變量,相當於聲明了屬性名對應的訪問方法,遵守協議的類需要實現對應的訪問器方法,否則運行報錯
分類中聲明屬性,警告提示需要手動實現訪問器方法(Swift中叫計算型屬性),而分類中不能創建成員變量,可以在手寫訪問器方法中使用runtime的 objc_setAssociatedObject方法關聯對象間接創建屬性(靜態庫添加屬性)
拓展裏可以聲明屬性,直接可以使用
2> 繼承和類別的區別
1> 使用繼承:
1.1> 添加新方法和父類方法一致,但父類方法仍需要使用
1.2> 添加新屬性
2> 類別:
2.1> 針對系統提供的一些類,系統本身不提倡繼承,因為這些類的內部實現對繼承有所限制(NSString initWithFormat繼承崩潰)
2.2> 類別可以將自己構建的類中的方法進行分組,對於大型的類,提高可維護性
3> 分類的作用
將類的實現分散到多個不同文件或多個不同框架中。
創建對私有方法的前向引用。
向對象添加非正式協議。
4> 分類的局限性
無法向類中添加新的實例變量,類別沒有位置容納實例變量。
名稱沖突,即當類別中的方法與原始類方法名稱沖突時,類別具有更高的優先級。類別方法將完全取代初始方法從而無法再使用初始方法。
無法添加實例變量的局限可以使用字典對象解決.
2.extension
3.protocol
三.Foundation
1.字符串
2.NSArray和NSDictionary
1> iOS遍歷數組/字典的方法
數組: for循環 for in enumerateObjectsUsingBlock(正序) enumerateObjectsWithOptions:usingBlock:(多一個遍歷選項,不保證順序)
字典:
1. for(NSString *object in [testDic allValues])
2. for(id akey in [testDic allKeys]){
[sum appendString:[testDic objectForKey:akey]]; }
3. [testDic enumerateKeysAndObjectsUsingBlock:^(idkey,idobj,BOOL*stop) {
[sum appendString:obj]; } ];
速度: 對於數組, 增強for最快,普通for和block速度差不多,增強最快是因為增強for語法會對容器裏的元素的內存地址建立緩沖,遍歷的時候直接從緩沖中取元素地址而不是通過調用方法來獲取,所以效率高.這也是使用增強for時不能在循環體中修改容器元素的原因之一(可以在循環體中添加標記,在循環體外修改元素)
對於字典,allValues最快,allKey和block差不多,原因是allKey需要做objcetForKey的方法
3.NSValue NSNumber
1> 歸檔視圖尺寸,坐標
四.關鍵字
1.@property
1>readwrite,readonly,assign,retain,copy,nonatomic屬性的作用
@property是一個屬性訪問聲明,擴號內支持以下幾個屬性:
1.1> getter setter
getter=getterName,setter=setterName,設置setter與getter的方法名
1.2> weak assign strong copy
assign 用於非指針變量。用於基礎數據類型 (例如NSInteger)和C數據類型(int, float, double, char, 等),另外還有id,其setter方法直接賦值,不進行任何retain操作
weak 用於指針變量,比assign多了一個功能,當對象消失後自動把指針變成nil,由於消息發送給空對象表示無操作,這樣有效的避免了崩潰(野指針),為了解決原類型與循環引用問題
strong 用於指針變量,setter方法對參數進行release舊值再retain新值
copy 用於指針變量,setter方法進行copy操作,與retain處理流程一樣,先舊值release,再copy出新的對象,retainCount為1。這是為了減少對上下文的依賴而引入的機制。copy是在你不希望a和b共享一塊內存時會使用到。a和b各自有自己的內存。
1.3> readwrite,readonly,設置可供訪問級別
1.4> nonatomic,非原子性訪問,不加同步,多線程並發訪問會提高性能。註意,如果不加此屬性,則默認是兩個訪問方法都為原子型事務訪問。所以約定俗成只在主線程更新UI,防止多線程設置UI屬性,出現資源搶奪現象
2> 如何避免循環引用
兩個對象相互強引用,都無法release,解決辦法為一個使用strong,一個使用assign(weak)
3> delegate的屬性為什麽使用assign/weak
避免出現循環引用,場景如UITableViewController強引用視圖UITableView,而該視圖的代理又是控制器,為避免循環引用,讓delegate為弱引用
2.copy
1> copy的使用場景
當多個指針指向同一個對象時,為避免一個指針對對象的改動對其他指針的使用產生影響,使用copy來創建對象的副本
如頁面間傳值使用copy,A向B控制器傳屬性(屬性為自定義對象),為避免因A的屬性變化對B的屬性產生影響
再如多人開發或封裝庫,在不明確傳入值為可變還是不可變的情況下,使用copy更安全
2> 什麽是深拷貝淺拷貝
對於非容器類對象,不可變對象進行copy操作為淺拷貝,引用計數器加1,其他三種為深拷貝
對於容器類對象,基本和非容器類對象一致,但註意其深拷貝是對象本身是對象復制,其中元素仍為指針復制,系統將initWithArray方法歸為了元素深拷貝,但其實如果元素為不可變元素,仍為指針復制,使用歸解檔可以實現真正的深拷貝,元素也是對象拷貝NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject: array]];
3> 字符串什麽時候使用copy,strong
屬性引用的對象由兩種情況,可變和不可變字符串
引用對象不可變情況下,copy和strong一樣,copy為淺拷貝
引用對象可變情況下,如果希望屬性跟隨引用對象變化,使用strong,希望不跟隨變化使用copy
4> 字符串所在內存區域
@“abc” 常量區 stringwithformat 堆區
5> mutablecopy和copy @property(copy) NSMutableArray *arr;這樣寫有什麽問題
mutablecopy返回可變對象,copy返回不可變對象
6> 如何讓自定義類可以使用copy修飾符
實現<NSCopying>協議,重寫copyWithZone方法
五.runtime/消息轉發機制
1.runtime http://www.cocoachina.com/ios/20150715/12540.html
1> 什麽是runtime
runtime是一套比較底層的純C語言API, 屬於1個C語言庫, 包含了很多底層的C語言API。
在我們平時編寫的OC代碼中, 程序運行過程時, 其實最終都是轉成了runtime的C語言代碼, runtime算是OC的幕後工作者,objc_msgSend
2> runtime幹什麽用,使用場景
runtime是屬於OC的底層, 可以進行一些非常底層的操作(用OC是無法現實的, 不好實現)
在程序運行過程中, 動態創建一個類(比如KVO的底層實現) objc_allocateClassPair,class_addIvar,objc_registerClassPair
在程序運行過程中, 動態地為某個類添加屬性\方法, 修改屬性值\方法(修改封裝的框架) objc_setAssociatedObject object_setIvar
遍歷一個類的所有成員變量(屬性)\所有方法(字典轉模型,歸解檔) class_copyIvarList class_copyPropertyList class_copyMethodList
2.消息機制
1> 消息轉發的原理
當向一個對象發送消息時,objc_msgSend方法根據對象的isa指針找到對象的類,然後在類的調度表(dispatch table)中查找selector。如果無法找到selector,objc_msgSend通過指向父類的指針找到父類,並在父類的調度表(dispatch table)中查找selector,以此類推直到NSObject類。一旦查找到selector,objc_msgSend方法根據調度表的內存地址調用該實現。 通過這種方式,message與方法的真正實現在執行階段才綁定。
為了保證消息發送與執行的效率,系統會將全部selector和使用過的方法的內存地址緩存起來。每個類都有一個獨立的緩存,緩存包含有當前類自己的 selector以及繼承自父類的selector。查找調度表(dispatch table)前,消息發送系統首先檢查receiver對象的緩存。
緩存命中的情況下,消息發送(messaging)比直接調用方法(function call)只慢一點點點點。
2> SEL isa super cmd 是什麽
sel: 一種類型,表示方法名稱,類似字符串(可互轉)
isa:在方法底層對應的objc_msgSend調用時,會根據isa找到對象所在的類對象,類對象中包含了調度表(dispatch table),該表將類的sel和方法的實際內存地址關聯起來
super_class:每一個類中還包含了一個super_class指針,用來指向父類對象
_cmd在Objective-C的方法中表示當前方法的selector,正如同self表示當前方法調用的對象實例
IMP定義為 id (*IMP) (id, SEL, …)。這樣說來, IMP是一個指向函數的指針,這個被指向的函數包括id(“self”指針),調用的SEL(方法名),再加上一些其他參數.說白了IMP就是實現方法
3> 動態綁定
—在運行時確定要調用的方法
動態綁定將調用方法的確定也推遲到運行時。在編譯時,方法的 調用並不和代碼綁定在一起,只有在消實發送出來之後,才確定被調用的代碼。通過動態類型和動態綁定技術,您的代碼每次執行都可以得到不同的結果。運行時因 子負責確定消息的接收者和被調用的方法。運行時的消息分發機制為動態綁定提供支持。當您向一個動態類型確定了的對象發送消息時,運行環境系統會通過接收者 的isa指針定位對象的類,並以此為起點確定被調用的方法,方法和消息是動態綁定的。而且,您不必在Objective-C 代碼中做任何工作,就可以自動獲取動態綁定的好處。您在每次發送消息時,特別是當消息的接收者是動態類型已經確定的對象時,動態綁定就會例行而透明地發生。
六.內存管理
1.內存區域
1>堆和棧的區別
管理方式:對於棧來講,是由編譯器自動管理,無需我們手工控制;對於堆來說,釋放工作由程序員控制,容易產生memory leak。
申請大小:
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
碎片問題:
對於堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低。對於棧來講,則不會存在這個問題,因為棧是先進後出的隊列,他們是如此的一一對應,以至於永遠都不可能有一個內存塊從棧中間彈出
分配方式:
堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配。動態分配由alloca函數進行分配,但是棧的動態分配和堆是不同的,他的動態分配是由編譯器進行釋放,無需我們手工實現。
分配效率:
棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很復雜的。
2.iOS內存管理
1> 字符串的內存管理
創建字符串的內存空間 堆 常量區
2> 循環引用
delegate屬性的內存策略
block循環引用 實際場景
3> autorelease的使用 工廠方法為什麽不釋放對象 ARC下autorelease的使用場景
避免內存峰值
SDWebimage中加載gif圖片 大循環
棧結構 棧頂
統一發release消息
4> ARC和MRC的混用
4.1> MRC>ARC
把MRC的代碼轉換成ARC的代碼,刪除內存管理操作(手動)
xcode提供了自動將MRC轉換成ARC的功能,操作菜單欄edit -> Refacotor(重構) -> Convert to Objective-C ARC
4.2> ARC>MRC
在ARC項目中繼續使用MRC編譯的類,在編譯選項中標識MRC文件即可"-fno-objc-arc"
在MRC項目中繼續使用ARC編譯的類在編譯選項中標識MRC文件即可"-fobjc-arc"
3.跨平臺
3> OC和C框架對象引用
oc和c 橋接 三個橋接關鍵字都是幹麽的 __bridge 不更改歸屬權 __bridge_transfer 所有權給OC __bridge_retain 解除OC的所有權
ios5/6/7/8 內存方面的區別?
ios5.自動引用計數 (ARC)
ios6.UICollectionView ( 內存重用機制,圖片展示瀑布流實現 ) 在didReceiveMemoryWarning中處理內存(6之前在ViewDidUnload中) http://blog.csdn.net/likendsl/article/details/8199350
ios7.iOS7以後強制使用ARC
ios8
七.數據傳遞
1.block
1> block屬性為什麽用copy?
棧->堆
2> block使用註意什麽?
循環引用 修改外部變量
3> block的主要使用場景 ?
動畫
數組字典排序遍歷
回調狀態
錯誤控制
多線程GCD
4>block原理
block屬性是指向結構體的指針,
2.Delegate
4> 什麽時候用delegate,什麽時候用Notification
delegate針對one-to-one關系,並且reciever可以返回值給sender,notification 可以針對one-to-one/many/none,reciever無法返回值給sender.所以,delegate用於sender希望接受到 reciever的某個功能反饋值,notification用於通知多個object某個事件。
5> delegate和block
block使代碼更緊湊,便於閱讀,delegate可以設置必選和可選的方法實現,相比block
block可以訪存局部變量. 不需要像以前的回調一樣,把在操作後所有需要用到的數據封裝成特定的數據結構, 你完全可以直接訪問局部變量.
3.KVC和KVO
1> 如何調用私有變量 如何修改系統的只讀屬性 KVC的查找順序
KVC在某種程度上提供了訪問器的替代方案。不過訪問器方法是一個很好的東西,以至於只要是有可能,KVC也盡量再訪問器方法的幫助下工作。為了設置或者返回對象屬性,KVC按順序使用如下技術:
①檢查是否存在-<key>、-is<key>(只針對布爾值有效)或者-get<key>的訪問器方法,如果有可能,就是用這些方法返回值;
檢查是否存在名為-set<key>:的方法,並使用它做設置值。對於 -get<key>和 -set<key>:方法,將大寫Key字符串的第一個字母,並與Cocoa的方法命名保持一致;
②如果上述方法不可用,則檢查名為-_<key>、-_is<key>(只針對布爾值有效)、-_get<key>和-_set<key>:方法;
③如果沒有找到訪問器方法,可以嘗試直接訪問實例變量。實例變量可以是名為:<key>或_<key>;
④如果仍為找到,則調用valueForUndefinedKey:和setValue:forUndefinedKey:方法。這些方法的默認實現都是拋出異常,我們可以根據需要重寫它們。
2> 什麽是鍵-值,鍵路徑是什麽
模型的性質是通過一個簡單的鍵(通常是個字符串)來指定的。視圖和控制器通過鍵來查找相應的屬性值。在一個給定的實體中,同一個屬性的所有值具有相同的數據類型。鍵-值編碼技術用於進行這樣的查找—它是一種間接訪問對象屬性的機制。
鍵路徑是一個由用點作分隔符的鍵組成的字符串,用於指定一個連接在一起的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每個鍵的值也是相對於其前面的性質。鍵路徑使您可以以獨立於模型實現的方式指定相關對象的性質。通過鍵路徑,您可以指定對象圖中的一
個任意深度的路徑,使其指向相關對象的特定屬性。
3> 什麽是KVC和KVO
KVC(Key-Value-Coding)內部的實現:一個對象在調用setValue的時候,(1)首先根據方法名找到運行方法的時候所需要的環境參數。(2)他會從自己isa指針結合環境參數,找到具體的方法實現的接口。(3)再直接查找得來的具體的方法實現。KVO(Key-Value- Observing):當觀察者為一個對象的屬性進行了註冊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類,而不是真實的類。所以 isa指針其實不需要指向實例對象真實的類。所以我們的程序最好不要依賴於isa指針。在調用類的方法的時候,最好要明確對象實例的類名
4> kvo的實現機制
當某個類的對象第一次被觀察時,系統就會在運行時動態地創建該類的一個派生類,在這個派生類中重寫原類中被觀察屬性的setter方法,派生類在被重寫的setter方法實現真正的通知機制(Person->NSKVONotifying_Person).
派生類重寫了 class 方法以“欺騙”外部調用者它就是起初的那個類。然後系統將這個對象的isa指針指向這個新誕生的派生類,因此這個對象就成為該派生類的對象了,因而在該對象上對setter的調用就會調用重寫的setter,從而激活鍵值通知機制。此外,派生類還重寫了dealloc方法來釋放資源。
5> kvo使用場景
①實現上下拉刷新控件 contentoffset
②webview混合排版 contentsize
③監聽模型屬性實時更新UI
UI
一.控件
1.屬性
1> frame和bounds的區別
frame:可表示尺寸和位置,與父視圖坐標系的關系,位置以自己的左上角為原點,可用於形變和位移
bounds:可表示尺寸和位置,與自身視圖坐標系的關系,大多數情況(滾動視圖的子視圖等除外)以自己的中心點為原點,可用於形變
center:只表示位置,表示自己中心的坐標,可用於位移
2> trasform
修改位移\形變\旋轉,transform不同於board\center\frame,前者中記錄的是形變的數據,不發生形變其值是空的,所以我們需要新建結構體,用CGAffineTransform(仿射變換)函數給對象結構體屬性賦值,而後者是控件的固有屬性,內存數據是始終存在的,當我們用他們做移動等操作時,是改變其值,所以是結構體賦值三步曲,不用CG的函數
使用情景區別: transform一般用於有來有回的變化,而frame是有去無回
2.UITableview
1> 自定義高度
1.1>新建一個繼承自UITableViewCell的類
1.2>重寫initWithStyle:reuseIdentifier:方法
1.3>添加所有需要顯示的子控件(不需要設置子控件的數據和frame, 子控件要添加到contentView中)
1.4>進行子控件一次性的屬性設置(有些屬性只需要設置一次, 比如字體\固定的圖片)
1.5>提供2個模型
數據模型: 存放文字數據\圖片數據
frame模型: 存放數據模型\所有子控件的frame\cell的高度
1.6>cell擁有一個frame模型(不要直接擁有數據模型)
1.7>重寫frame模型屬性的setter方法: 在這個方法中設置子控件的顯示數據和frame
3.UICollectionView
1> 如何實現瀑布流,流水布局
通過實現UICollectionViewDelegateFlowLayout去改變單元格大小
2> 和UITableView的使用區別
1)必須使用下面的方法進行Cell類的註冊:
- - (void)registerClass:forCellWithReuseIdentifier:
- - (void)registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
- - (void)registerNib:forCellWithReuseIdentifier:
2)collectionView與tableView最大的不同點,collectionView必須要使用自己的layout(UICollectionViewLayout)
如:
- UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
- flowLayout.itemSize = CGSizeMake(52, 52); // cell大小
- flowLayout.minimumInteritemSpacing = 1; // cell間距
- flowLayout.minimumLineSpacing = 1; // cell行距
- flowLayout.sectionInset = (UIEdgeInsets){81,1,1,1}; // cell邊距
創建collectionView需要帶Layout的初始化方法:
- - (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
二.生命周期
1> 應用的生命周期
各個程序運行狀態時代理的回調:
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions 告訴代理進程啟動但還沒進入狀態保存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 告訴代理啟動基本完成程序準備開始運行
- (void)applicationWillResignActive:(UIApplication *)application 當應用程序將要入非活動狀態執行,在此期間,應用程序不接收消息或事件,比如來電話了
- (void)applicationDidBecomeActive:(UIApplication *)application 當應用程序入活動狀態執行,這個剛好跟上面那個方法相反
- (void)applicationDidEnterBackground:(UIApplication *)application 當程序被推送到後臺的時候調用。所以要設置後臺繼續運行,則在這個函數裏面設置即可
- (void)applicationWillEnterForeground:(UIApplication *)application 當程序從後臺將要重新回到前臺時候調用,這個剛好跟上面的那個方法相反。
- (void)applicationWillTerminate:(UIApplication *)application 當程序將要退出是被調用,通常是用來保存數據和一些退出前的清理工作。
2> 視圖的生命周期
loadView - 默認調用super方法,根據控制器創建方式加載視圖,重寫後將根據重寫方法創建視圖
viewDidLoad-視圖加載完成
viewWillAppear-UIViewController對象的視圖即將加入窗口時調用;
viewDidApper-UIViewController對象的視圖已經加入到窗口時調用;
viewWillDisappear-UIViewController對象的視圖即將消失、被覆蓋或是隱藏時調用;
viewDidDisappear-UIViewController對象的視圖已經消失、被覆蓋或是隱藏時調用;
viewVillUnload-當內存過低時,需要釋放一些不需要使用的視圖時,即將釋放時調用;
viewDidUnload-當內存過低,釋放一些不需要的視圖時調用。
四.核心繪圖
6> View和layer的區別
圖層不會直接渲染到屏幕上,UIView是iOS系統中界面元素的基礎,所有的界面元素都是繼承自它。它本身完全是由CoreAnimation來實現的。它真正的繪圖部分,是由一個CALayer類來管理。UIView本身更像是一個CALayer的管理器。一個UIView上可以有n個CALayer,每個layer顯示一種東西,增強UIView的展現能力。
6.1>都可以顯示屏幕效果
6.2> 如果需要用戶交互就要用UIVIew,其可接收觸摸事件(繼承UIResponder),而CALayer不能接收觸摸事件
6.3> 如果沒有用戶交互可選用CALayer,因為其所在庫較小,占用的資源較少
7> new和alloc init的區別
采用new的方式只能采用默認的init方法完成初始化,采用alloc的方式可以用其他定制的初始化方法。
六.事件處理
1> 描述響應者鏈條
當觸摸事件發生時,壓力轉為電信號,iOS系統將產生UIEvent對象,記錄事件產生的時間和類型,然後系統將事件加入到一個由UIApplication管理的事件隊列中。
UIApplication會從事件隊列中取出最前面的事件,並將事件分發下去以便處理,通常,先發送事件給應用程序的主窗口(keyWindow)
主窗口會在視圖層次結構中找到一個最合適的視圖來處理觸摸事件(從父到子,從後到前),這也是整個事件處理過程的第一步
找到合適的視圖控件後,就會調用視圖控件的touches方法來作具體的事件處理
4.Runloop
1> 每個線程上都有一個runloop,主線程默認開啟,輔助線程需要手動開啟,主要用於
- 使用端口或自定義輸入源來和其他線程通信
- 使用線程的定時器
- Cocoa中使用任何performSelector…的方法
- 使線程周期性工作
七.屏幕適配
多線程
一.資源搶奪
2> 資源搶奪解決方案
@sychronized{ }
dispatch_barrier_async
NSLock NSCondition
dispatch_semaphore_wait
二.iOS多線程技術
3> 對比iOS中的多線程技術
3.1> pthread
pthread跨平臺,使用難度大,需要手動管理線程生命周期
pthread_create創建線程,傳參線程標記,線程屬性,初始函數,函數參數
3.2> NSThread
NSThread需要手動管理線程生命周期和
3.3> GCD
3.4> NSOperation
GCD是純C語言的API,NSOperationQueue是基於GCD的OC版本封裝
3.2> GCD僅僅支持FIFO隊列,只可以設置隊列的優先級,而NSOperationQueue中的每一個任務都可以被重新設置優先級(setQueuePriority:),從而實現不同操作的執行順序調整
3.3> GCD不支持異步操作之間的依賴關系設置。如果某個操作的依賴另一個操作的數據,使用NSOperationQueue能夠設置依賴按照正確的順序執行操作(addDependency:)。GCD則沒有內建的依賴關系支持(只能通過Barrior和同步任務手動實現)。
3.4> NSOperationQueue方便停止隊列中的任務(cancelAllOperations, suspended),GCD不方便停止隊列中的任務.
3.5> NSOperationQueue支持KVO,可以監測operation是否正在執行(isExecuted)、是否結束(isFinished),是否取消(isCanceld)
3.6> GCD的執行速度比NSOperationQueue快
3.7> NSOperationQueue可設置最大並發數量(節電),GCD具有dispatch_once(只執行一次,單例)和dispatch_after(延遲執行)功能
3.8> NSObject分類(perform)和NSThread遇到對象分配需要手動內存管理,手動管理線程生命周期
3.9> NSThread查看線程
3.10> NSObject分類線程通信
4> 原子屬性
原子屬性采用的是"多讀單寫"機制的多線程策略
"多讀單寫"縮小了鎖範圍,比互斥鎖的性能好
規定只在主線程更新UI,就是因為如果在多線程中更新,就需要給UI對象加鎖,防止資源搶占寫入錯誤,但是這樣會降低UI交互的性能,所以ios設計讓所有UI對象都是非線程安全的(不加鎖),並規定只在主線程中更新UI,規避多線程搶占資源問題
三.其他
5> 多線程優缺點
優點:
使應用程序的響應速度更快,用戶界面在進行其他工作的同時仍始終保持活動狀態;
優化任務執行,適當提高資源利用率(cpu, 內存);
缺點:
線程占用內存空間,管理線程需要額外的CPU開銷,開啟大量線程,降低程序性能;
增加程序復雜度,如線程間通信,多線程的資源共享等;
1> 在多線程中使用通知需要註意什麽問題?
網絡
一.網絡基礎
1.數據解析
1> XML解析方式
SAX 方式解析
-只讀
-速度快
-從上向下
-通過5個代理方法解析,每個代理方中都需要寫一些代碼!
-如果要實現SAX解析,思路最重要!
-適合比價大的XML的解析
DOM解析的特點
-一次性將XML全部加載到內存,以樹形結構
-好處,可以動態的修改,添加,刪除節點
-內存消耗非常大!尤其橫向節點越深!
-iOS默認不支持 DOM 解析!
-在 MAC 端,或者服務器端開發,都基本上使用 DOM 解析
-在 iOS 端如果需要使用 DOM 方式解析,可以使用第三方框GData/KissXML(XMPP)
-適合比較小的 XML 文件
-在 MAC 中,蘋果提供了一個 NSXML 的類,能夠做 DOM 解析,在 iOS 不能使用!
2.網絡協議
1>TCP如何防止亂序和丟包
TCP數據包的頭格式中有兩個概念,Sequence Number是數據包的序號,用來解決網絡包亂序(reordering)問題。Acknowledgement Number就是ACK——用於確認收到,用來解決不丟包的問題。
位碼即tcp標誌位,有6種標示:SYN(synchronous建立聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)Sequence number(順序號碼) Acknowledge number(確認號碼).
SeqNum的增加是和傳輸的字節數相關的,TCP傳輸數據時,A主機第一次傳輸1440個字節,seq=1,那麽第二次時seq = 1441,B拼接數據就是根據seq進行拼接的,seq數字不斷累加避免了亂序.B主機收到第一次數據包以後會返回ack = 1441.
A主機收到B的ack = 1441時,就知道第一個數據包B已收到. 如果B沒有收到第一次的數據包,那麽B再收到A的數據包時,他就會發ack = 1回去,A收到B的回復,發現B沒有收到第一次數據包,就會重發第一次數據包,這樣就可以防止丟包.
2>描述一下三次握手
第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。完成三次握手,客戶端與服務器開始傳送數據.
3> TCP與UDP的區別:
3.1>基於連接與無連接;
3.2>對系統資源的要求(TCP較多,UDP少);
3.3>UDP程序結構較簡單;
3.4>流模式與數據報模式 ;
3.5>TCP保證數據正確性,UDP可能丟包,TCP保證數據順序,UDP不保證。
4>http和scoket通信的區別
http是客戶端用http協議進行請求,發送請求時候需要封裝http請求頭,並綁定請求的數據,服務器一般有web服務器配合(當然也非絕對)。 http請求方式為客戶端主動發起請求,服務器才能給響應,一次請求完畢後則斷開連接,以節省資源。服務器不能主動給客戶端響應(除非采取http長連接技術)。iPhone主要使用類是NSUrlConnection。
scoket是客戶端跟服務器直接使用socket“套接字”進行連接,並沒有規定連接後斷開,所以客戶端和服務器可以保持連接通道,雙方都可以主動發送數據。一般在遊戲開發或股票開發這種要求即時性很強並且保持發送數據量比較大的場合使用。主要使用類是CFSocketRef。
3.網絡傳輸
1>DNS是如何工作的
DNS是domain name server的簡稱,每個網絡的計算機都有ip,但是不好記,所以用域名替代(如www.baidu.com),在 Internet 上真實在辨識機器的還是 IP,所以當使用者輸入Domain Name 後,瀏覽器必須要先去一臺有 Domain Name 和IP 對應資料的主機去查詢這臺電腦的 IP,而這臺被查詢的主機,我們稱它為 Domain Name Server,簡稱DNS,例如:當你輸入www.pchome.com.tw時,瀏覽器會將www.pchome.com.tw這個名字傳送到離他最近的 DNS Server 去做辨識,如果查到,則會傳回這臺主機的 IP,進而跟它索取資料,但如果沒查到,就會發生類似 DNS NOT FOUND 的情形,所以一旦DNS Server當機,就像是路標完全被毀壞,沒有人知道該把資料送到那裏
二.網絡安全/加密
料送到那裏
三.數據存儲
1.數據存儲技術
1> 數據存儲的幾種方式
1.1> plist xml
1.2> 偏好設置
1.3> 歸檔 Document 自定義對象 NSCoding協議
如何使用plist保存視圖尺寸 NSValue
2> 沙盒目錄結構
2.1> Library Caches Preferences
2.2> Documents
2.3> tmp
2.數據庫技術(SQLite&CoreData)
四.Html5/oc&js互調
oc>js:[self.webView stringByEvaluatingJavaScriptFromString:“window.location.href = xxx”];
js>oc: 利用hmtl中js的重定向技術,<Script> window.location.href = www.baidu.com//method:dosomething </Script>
使用方法截取重定向
(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
五.iOS網絡框架
1> NSURLConnection和NSURLSession的區別
1.1> 異步請求不需要NSOperation包裝
1.2> 支持後臺運行的網絡任務(後臺上傳下載)
1.3> 根據每個Session做配置(http header,Cache,Cookie,protocal,Credential),不再在整個App層面共享配置
1.4> 支持網絡操作的取消和斷點續傳(繼承系統類,重新main方法)
1.5> 改進了授權機制的處理
項目
1.實用技術
2.知名第三方框架
3.開發技巧
1> description方法
Swift
1> Swift和OC的區別
1.1> Swift沒有地址/指針的概念
1.2> 泛型
1.3> 類型嚴謹 對比oc的動態綁定
6.設計模式
1> 常用的設計模式
代理 觀察者 工廠 單例 策略
2> 代理屬性的內存策略是什麽,為什麽?
3> 觀察者模式的使用場景
4> 工廠模式(類方法)為什麽沒有釋放對象? autorelease工作原理? arc下還需要手動使用autorelease嗎?為什麽?什麽場景?
5> 手寫單例
6> 策略 cell多種響應效果 代理方法
(一)代理模式
應用場景:當一個類的某些功能需要由別的類來實現,但是又不確定具體會是哪個類實現。
優勢:解耦合
敏捷原則:開放-封閉原則
實例:tableview的 數據源delegate,通過和protocol的配合,完成委托訴求。
列表row個數delegate
自定義的delegate
(二)觀察者模式
應用場景:一般為model層對controller和view進行的通知方式,不關心誰去接收,只負責發布信息。
優勢:解耦合
敏捷原則:接口隔離原則,開放-封閉原則
實例:Notification通知中心,註冊通知中心,任何位置可以發送消息,註冊觀察者的對象可以接收。
kvo,鍵值對改變通知的觀察者,平時基本沒用過。
(三)MVC模式
應用場景:是一中非常古老的設計模式,通過數據模型,控制器邏輯,視圖展示將應用程序進行邏輯劃分。
優勢:使系統,層次清晰,職責分明,易於維護
敏捷原則:對擴展開放-對修改封閉
實例:model-即數據模型,view-視圖展示,controller進行UI展現和數據交互的邏輯控制。
(四)單例模式
應用場景:確保程序運行期某個類,只有一份實例,用於進行資源共享控制。
優勢:使用簡單,延時求值,易於跨模塊
敏捷原則:單一職責原則
實例:[UIApplication sharedApplication]。
註意事項:確保使用者只能通過 getInstance方法才能獲得,單例類的唯一實例。
java,C++中使其沒有公有構造函數,私有化並覆蓋其構造函數。
object c中,重寫allocWithZone方法,保證即使用戶用 alloc方法直接創建單例類的實例,返回的也只是此單例類的唯一靜態變量。
(五)策略模式
應用場景:定義算法族,封裝起來,使他們之間可以相互替換。
優勢:使算法的變化獨立於使用算法的用戶
敏捷原則:接口隔離原則;多用組合,少用繼承;針對接口編程,而非實現。
實例:排序算法,NSArray的sortedArrayUsingSelector;經典的鴨子會叫,會飛案例。
註意事項:1,剝離類中易於變化的行為,通過組合的方式嵌入抽象基類
2,變化的行為抽象基類為,所有可變變化的父類
3,用戶類的最終實例,通過註入行為實例的方式,設定易變行為
防止了繼承行為方式,導致無關行為汙染子類。完成了策略封裝和可替換性。
(六)工廠模式
應用場景:工廠方式創建類的實例,多與proxy模式配合,創建可替換代理類。
優勢:易於替換,面向抽象編程,application只與抽象工廠和易變類的共性抽象類發生調用關系。
敏捷原則:DIP依賴倒置原則
實例:項目部署環境中依賴多個不同類型的數據庫時,需要使用工廠配合proxy完成易用性替換
註意事項:項目初期,軟件結構和需求都沒有穩定下來時,不建議使用此模式,因為其劣勢也很明顯,
增 加了代碼的復雜度,增加了調用層次,增加了內存負擔。所以要註意防止模式的濫用。
六.框架
1.SDWebimage
1> SDWebimage的緩存機制
- UIImageView+WebCache: setImageWithURL:placeholderImage:options: 先顯示 placeholderImage ,同時由SDWebImageManager 根據 URL 來在本地查找圖片。
- SDWebImageManager: downloadWithURL:delegate:options:userInfo: SDWebImageManager是將UIImageView+WebCache同SDImageCache鏈接起來的類, SDImageCache: queryDiskCacheForKey:delegate:userInfo:用來從緩存根據CacheKey查找圖片是否已經在緩存中
- 如果內存中已經有圖片緩存, SDWebImageManager會回調SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
- 而 UIImageView+WebCache 則回調SDWebImageManagerDelegate: webImageManager:didFinishWithImage:來顯示圖片。
- 如果內存中沒有圖片緩存,那麽生成 NSInvocationOperation 添加到隊列,從硬盤查找圖片是否已被下載緩存。
- 根據 URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進行的操作,所以回主線程進行結果回調
- notifyDelegate:
- 如果上一操作從硬盤讀取到了圖片,將圖片添加到內存緩存中(如果空閑內存過小,會先清空內存緩存)。SDImageCacheDelegate 回調 imageCache:didFindImage:forKey:userInfo:進而回調展示圖片。
- 如果從硬盤緩存目錄讀取不到圖片,說明所有緩存都不存在該圖片,需要下載圖片,回調
- imageCache:didNotFindImageForKey:userInfo:
- 共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片。
- 圖片下載由 NSURLConnection 來做,實現相關 delegate 來判斷圖片下載中、下載完成和下載失敗。
- connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進度加載效果。
- connectionDidFinishLoading: 數據下載完成後交給 SDWebImageDecoder 做圖片解碼處理。
- 圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主線程 UI。如果有需要對下載的圖片進行二次處理,最好也在這裏完成,效率會好很多。
- 在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調給 SDWebImageDownloader。
- imageDownloader:didFinishWithImage: 回調給 SDWebImageManager 告知圖片下載完成。
- 通知所有的 downloadDelegates 下載完成,回調給需要的地方展示圖片。
- 將圖片保存到 SDImageCache 中,內存緩存和硬盤緩存同時保存。
- 寫文件到硬盤在單獨 NSInvocationOperation 中完成,避免拖慢主線程。
- 如果是在iOS上運行,SDImageCache 在初始化的時候會註冊notification 到 UIApplicationDidReceiveMemoryWarningNotification 以及 UIApplicationWillTerminateNotification,在內存警告的時候清理內存圖片緩存,應用結束的時候清理過期圖片。
- SDWebImagePrefetcher 可以預先下載圖片,方便後續使用。
位運算
NSCache
特點: a> 線程安全的 b> 當內存不足的時候,自動釋放 c> 緩存數量和緩存成本
區別NSMutableDictionary
1> 不能也不應該遍歷 2> NSCache對key強引用,NSMutableDictionary對key進行copy
2.AFN
1>實現原理
AFN的直接操作對象AFHTTPClient不同於ASI,是一個實現了NSCoding和NSCopying協議的NSObject子類。 AFHTTPClient是一個封裝了一系列操作方法的“工具類”,處理請求的操作類是一系列單獨的,基於NSOperation封裝 的,AFURLConnectionOperation的子類。AFN的示例代碼中通過一個靜態方法,使用dispatch_once()的方式創建 AFHTTPClient的共享實例,這也是官方建議的使用方法。在創建AFHTTPClient的初始化方法中,創建了OperationQueue並 設置一系列參數默認值。在getPath:parameters:success:failure方法中創建NSURLRequest,以 NSURLRequest對象實例作為參數,創建一個NSOperation,並加入在初始化發方中創建的NSOperationQueue。以上操作都 是在主線程中完成的。在NSOperation的start方法中,以此前創建的NSURLRequest對象為參數創建NSURLConnection 並開啟連結。
2> 傳遞指針 如何使一個方法返回多個返回值
七.項目
3.混編
arc mrc混編
c c++混編
4.加密
八.算法
交換數值的幾種方法 中間變量 加減法 異或
二叉樹
鏈表
遞歸
iOS知識大全