主要的幾個大模塊
1基矮、block
一氛雪、
Block變量的聲明格式為: 返回值類型(^Block名字)(參數(shù)列表);
void(^aBlock)(NSString *x, NSString *y);聲明
Block變量的賦值格式為: Block變量 = ^(參數(shù)列表){函數(shù)體};
aBlock = ^(NSString *x, NSString *y){? 賦值
? ? NSLog(@"%@ love %@", x, y);
};
aBlock(@"Li Lei",@"Han Meimei"); 調(diào)用
二镶殷、
在Block中可以訪問局部變量;在聲明Block之后谱秽、調(diào)用Block之前對局部變量進行修改,在調(diào)用Block時局部變量值是修改之前的舊值冗栗;在Block中不可以直接修改局部變量。
__block修飾的局部變量? 就可以
全局變量 就可以
static靜態(tài)變量? 就可以
三宵凌、
? ? ? 如果對象內(nèi)部有一個Block屬性,而在Block內(nèi)部又訪問了該對象,那么會造成循環(huán)引用,解決循環(huán)引用的辦法是使用一個弱引用的指針指向該對象,然后在Block內(nèi)部使用該弱引用指針來進行操作,這樣避免了Block對對象進行強引用
?談?wù)刡lock使用時的注意點鞋囊?
1、在block內(nèi)部使用外部指針且會造成循環(huán)引用情況下,需要用__weak修飾外部指針__weak typeof(self) weakSelf = self;
2瞎惫、在block內(nèi)部如果調(diào)用了延時函數(shù)還使用弱指針會取不到該指針,因為已經(jīng)被銷毀了,需要在block內(nèi)部再將弱指針重新強引用一下__strong typeof(self) strongSelf = weakSelf;
3溜腐、如果需要在block內(nèi)部改變外部變量的話,需要在用__block修飾外部變量
?在Block中如何修改Block外部變量的值
我們最常見的做法就是在需要修改的變量前加上 __block 修飾
*解釋:很多時候,我們都直接這樣去操作瓜喇,但是為什么加上__block之后挺益,就可以這樣操作?
在內(nèi)存中分區(qū)大致可分為:
棧:用于存放臨時變量乘寒,處理速度快望众,但是因為棧內(nèi)存極小,容易產(chǎn)生內(nèi)存泄漏
堆:空間大伞辛,處理速度一般
只讀數(shù)據(jù)段:用于存放常量(字面常量烂翰,符號常量),不能被修改
數(shù)據(jù)段:全部變量
代碼段:代碼蚤氏,函數(shù)名等
通過上面的分區(qū)我們可以知道
變量聲明出來存放在棧上面
而block甘耿,默認存放在NSGlobalBlock 全局的block;我們常常把block和C中的函數(shù)做對比竿滨,此時也類似佳恬,NSGlobalBlock類似于函數(shù)捏境,存放在代碼段
當block內(nèi)部使用了外部的變量時,block的存放位置變成了NSMallockBlock(堆)
__block 修飾以后毁葱,會類似于橋接垫言,將被修飾的變量被block所持有,此時該變量也轉(zhuǎn)存到堆空間倾剿,所以此時Block內(nèi)部就可以對外部的變量進行修改
2.運行時機制-Runtime
runtime庫里面包含了跟類骏掀、成員變量、方法相關(guān)的API柱告,比如獲取類里面的所有成員變量,為類動態(tài)添加成員變量笑陈,動態(tài)改變類的方法實現(xiàn)际度,為類動態(tài)添加新的方法等 需要導(dǎo)入
1.是什么
1> runtime是一套比較底層的純C語言API, 屬于1個C語言庫, 包含了很多底層的C語言API
2> 平時編寫的OC代碼, 在程序運行過程中, 其實最終都是轉(zhuǎn)成了runtime的C語言代碼, runtime算是OC的幕后工作者
3> 舉例: OC : [[MJPerson alloc] init]
runtime : objc_msgSend(objc_msgSend("MJPerson" , "alloc"), "init")
2.用過么? 怎么用?
1> runtime是屬于OC的底層, 可以進行一些非常底層的操作(用OC是無法現(xiàn)實的, 不好實現(xiàn)) * 在程序運行過程中, 動態(tài)創(chuàng)建一個類(比如KVO的底層實現(xiàn)) * 在程序運行過程中, 動態(tài)地為某個類添加屬性方法, 修改屬性值方法 * 遍歷一個類的所有成員變量(屬性)所有方法
3.相關(guān)的頭文件
? ? ? 1> 頭文件
? ? ? 2> 相關(guān)應(yīng)用
* NSCoding(歸檔和解檔, 利用runtime遍歷模型對象的所有屬性)
* 字典 --> 模型 (利用runtime遍歷模型對象的所有屬性, 根據(jù)屬性名從字典中取出對應(yīng)的值, 設(shè)置到模型的屬性上)
* KVO(利用runtime動態(tài)產(chǎn)生一個類)
* 用于封裝框架(想怎么改就怎么改)
3> 相關(guān)函數(shù)
* objc_msgSend : 給對象發(fā)送消息
* class_copyMethodList : 遍歷某個類所有的方法
* class_copyIvarList : 遍歷某個類所有的成員變量
* class_.....
3.Runloop
RunLoop,是多線程的法寶涵妥,即一個線程一次只能執(zhí)行一個任務(wù)乖菱,執(zhí)行完任務(wù)后就會退出線程。主線程執(zhí)行完即時任務(wù)時會繼續(xù)等待接收事件而不退出蓬网。非主線程通常來說就是為了執(zhí)行某一任務(wù)的窒所,執(zhí)行完畢就需要歸還資源,因此默認是不運行RunLoop的帆锋;
每一個線程都有其對應(yīng)的RunLoop吵取,只是默認只有主線程的RunLoop是啟動的,其它子線程的RunLoop默認是不啟動的锯厢,若要啟動則需要手動啟動皮官;
在一個單獨的線程中,如果需要在處理完某個任務(wù)后不退出实辑,繼續(xù)等待接收事件捺氢,則需要啟用RunLoop;
NSRunLoop提供了一個添加NSTimer的方法剪撬,可以指定Mode摄乒,如果要讓任何情況下都回調(diào),則需要設(shè)置Mode為Common模式残黑;
實質(zhì)上馍佑,對于子線程的runloop默認是不存在的,因為蘋果采用了懶加載的方式梨水。如果我們沒有手動調(diào)用[NSRunLoop currentRunLoop]的話挤茄,就不會去查詢是否存在當前線程的RunLoop,也就不會去加載冰木,更不會創(chuàng)建穷劈。
4.多線程
NSThread:當需要進行一些耗時操作時會把耗時的操作放到線程中笼恰。線程同步:多個線程同時訪問一個數(shù)據(jù)會出問題,NSlock歇终、線程同步塊社证、@synchronized(self){}。
NSOperationQueue操作隊列(不需考慮線程同步問題)评凝。編程的重點都放在main里面追葡,NSInvocationOperation、BSBlockOperation奕短、自定義Operation宜肉。創(chuàng)建一個操作綁定相應(yīng)的方法,當把操作添加到操作隊列中時翎碑,操作綁定的方法就會自動執(zhí)行了谬返,當把操作添加到操作隊列中時,默認會調(diào)用main方法日杈。
GCD(``Grand Central Dispatch`)宏大的中央調(diào)度遣铝,串行隊列、并發(fā)隊列莉擒、主線程隊列酿炸;
同步和異步:同步指第一個任務(wù)不執(zhí)行完,不會開始第二個涨冀,異步是不管第一個有沒有執(zhí)行完填硕,都開始第二個。
串行和并行:串行是多個任務(wù)按一定順序執(zhí)行鹿鳖,并行是多個任務(wù)同時執(zhí)行廷支;
代碼是在分線程執(zhí)行,在主線程嘟列中刷新UI栓辜。
** 多線程編程是防止主線程堵塞恋拍、增加運行效率的最佳方法。**
Apple提供了NSOperation這個類藕甩,提供了一個優(yōu)秀的多線程編程方法施敢;
一個NSOperationQueue操作隊列,相當于一個線程管理器狭莱,而非一個線程僵娃,因為你可以設(shè)置這個線程管理器內(nèi)可以并行運行的線程數(shù)量等。
多線程是一個比較輕量級的方法來實現(xiàn)單個應(yīng)用程序內(nèi)多個代碼執(zhí)行路徑腋妙。
iPhoneOS下的主線程的堆棧大小是1M默怨。第二個線程開始就是512KB,并且該值不能通過編譯器開關(guān)或線程API函數(shù)來更改骤素,只有主線程有直接修改UI的能力匙睹。
?線程與進程的區(qū)別和聯(lián)系?
進程和線程都是由操作系統(tǒng)所體會的程序運行的基本單元愚屁,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應(yīng)用的并發(fā)性。
程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式痕檬。進程有獨立的地址空間霎槐,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響梦谜,而線程只是一個進程中的不同執(zhí)行路徑丘跌。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間唁桩,一個線程死掉就等于整個進程死掉闭树,所以多進程的程序要比=多線程的程序健壯,但在進程切換時荒澡,耗費資源較大报辱,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作仰猖,只能用線程,不能用進程奈籽。
5.內(nèi)存的使用和優(yōu)化的注意事項
重用問題:如UITableViewCells饥侵、UICollectionViewCells、UITableViewHeaderFooterViews設(shè)置正確的reuseIdentifier衣屏,充分重用躏升;
盡量把views設(shè)置為不透明:當opque為NO的時候,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果狼忱,可提高性能膨疏;
不要使用太復(fù)雜的XIB/Storyboard:載入時就會將XIB/storyboard需要的所有資源,包括圖片全部載入內(nèi)存钻弄,即使未來很久才會使用佃却。那些相比純代碼寫的延遲加載,性能及內(nèi)存就差了很多窘俺;
選擇正確的數(shù)據(jù)結(jié)構(gòu):學(xué)會選擇對業(yè)務(wù)場景最合適的數(shù)組結(jié)構(gòu)是寫出高效代碼的基礎(chǔ)饲帅。比如,數(shù)組: 有序的一組值瘤泪。使用索引來查詢很快灶泵,使用值查詢很慢,插入/刪除很慢对途。字典: 存儲鍵值對赦邻,用鍵來查找比較快。集合: 無序的一組值实檀,用值來查找很快惶洲,插入/刪除很快按声。
gzip/zip壓縮:當從服務(wù)端下載相關(guān)附件時,可以通過gzip/zip壓縮后再下載湃鹊,使得內(nèi)存更小儒喊,下載速度也更快。
延遲加載:對于不應(yīng)該使用的數(shù)據(jù)币呵,使用延遲加載方式怀愧。對于不需要馬上顯示的視圖,使用延遲加載方式余赢。比如芯义,網(wǎng)絡(luò)請求失敗時顯示的提示界面,可能一直都不會使用到妻柒,因此應(yīng)該使用延遲加載扛拨。
數(shù)據(jù)緩存:對于cell的行高要緩存起來,使得reload數(shù)據(jù)時举塔,效率也極高绑警。而對于那些網(wǎng)絡(luò)數(shù)據(jù),不需要每次都請求的央渣,應(yīng)該緩存起來计盒,可以寫入數(shù)據(jù)庫,也可以通過plist文件存儲芽丹。
處理內(nèi)存警告:一般在基類統(tǒng)一處理內(nèi)存警告北启,將相關(guān)不用資源立即釋放掉
重用大開銷對象:一些objects的初始化很慢,比如NSDateFormatter和NSCalendar拔第,但又不可避免地需要使用它們咕村。通常是作為屬性存儲起來,防止反復(fù)創(chuàng)建蚊俺。
避免反復(fù)處理數(shù)據(jù):許多應(yīng)用需要從服務(wù)器加載功能所需的常為JSON或者XML格式的數(shù)據(jù)懈涛。在服務(wù)器端和客戶端使用相同的數(shù)據(jù)結(jié)構(gòu)很重要;
使用Autorelease Pool:在某些循環(huán)創(chuàng)建臨時變量處理數(shù)據(jù)時,自動釋放池以保證能及時釋放內(nèi)存;
6.網(wǎng)絡(luò)
?TCP和UDP的區(qū)別于聯(lián)系
TCP為傳輸控制層協(xié)議泳猬,為面向連接肩钠、可靠的、點到點的通信暂殖;
UDP為用戶數(shù)據(jù)報協(xié)議价匠,非連接的不可靠的點到多點的通信;
TCP側(cè)重可靠傳輸呛每,UDP側(cè)重快速傳輸踩窖。
?TCP連接的三次握手
第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進入SYN_SEND狀態(tài)晨横,等待服務(wù)器確認洋腮;
第二次握手:服務(wù)器收到syn包箫柳,必須確認客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包啥供,即SYN+ACK包悯恍,此時服務(wù)器進入SYN+RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包伙狐,向服務(wù)器發(fā)送確認包ACK(ack=k+1)涮毫,此發(fā)送完畢,客戶端和服務(wù)器進入ESTABLISHED狀態(tài)贷屎,完成三次狀態(tài)罢防。
?Scoket連接和HTTP連接的區(qū)別:
HTTP協(xié)議是基于TCP連接的,是應(yīng)用層協(xié)議唉侄,主要解決如何包裝數(shù)據(jù)咒吐。Socket是對TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議属划,而是一個調(diào)用接口(API)恬叹,通過Socket,我們才能使用TCP/IP協(xié)議同眯。
HTTP連接:短連接绽昼,客戶端向服務(wù)器發(fā)送一次請求,服務(wù)器響應(yīng)后連接斷開嗽测,節(jié)省資源绪励。服務(wù)器不能主動給客戶端響應(yīng)(除非采用HTTP長連接技術(shù))肿孵,iPhone主要使用類NSURLConnection唠粥。
Socket連接:長連接,客戶端跟服務(wù)器端直接使用Socket進行連接停做,沒有規(guī)定連接后斷開晤愧,因此客戶端和服務(wù)器段保持連接通道,雙方可以主動發(fā)送數(shù)據(jù)蛉腌,一般多用于游戲.Socket默認連接超時時間是30秒官份,默認大小是8K(理解為一個數(shù)據(jù)包大小)烙丛。
?HTTP協(xié)議的特點舅巷,關(guān)于HTTP請求GET和POST的區(qū)別
?GET和POST的區(qū)別:
HTTP超文本傳輸協(xié)議,是短連接河咽,是客戶端主動發(fā)送請求钠右,服務(wù)器做出響應(yīng),服務(wù)器響應(yīng)之后忘蟹,鏈接斷開飒房。HTTP是一個屬于應(yīng)用層面向?qū)ο蟮膮f(xié)議搁凸,HTTP有兩類報文:請求報文和響應(yīng)報文。
HTTP請求報文:一個HTTP請求報文由請求行狠毯、請求頭部护糖、空行和請求數(shù)據(jù)4部分組成。
HTTP響應(yīng)報文:由三部分組成:狀態(tài)行嚼松、消息報頭嫡良、響應(yīng)正文。
GET請求:參數(shù)在地址后拼接惜颇,沒有請求數(shù)據(jù)皆刺,不安全(因為所有參數(shù)都拼接在地址后面),不適合傳輸大量數(shù)據(jù)(長度有限制凌摄,為1024個字節(jié))羡蛾。
GET提交、請求的數(shù)據(jù)會附在URL之后锨亏,即把數(shù)據(jù)放置在HTTP協(xié)議頭中痴怨。? 以?分割URL和傳輸數(shù)據(jù)器予,多個參數(shù)用&連接浪藻。如果數(shù)據(jù)是英文字母或數(shù)字,原樣發(fā)送乾翔,? 如果是空格无牵,轉(zhuǎn)換為+,如果是中文/其他字符慎恒,則直接把字符串用BASE64加密南窗。
POST請求:參數(shù)在請求數(shù)據(jù)區(qū)放著,相對GET請求更安全雷则,并且數(shù)據(jù)大小沒有限制辆雾。把提交的數(shù)據(jù)放置在HTTP包的包體中.
GET提交的數(shù)據(jù)會在地址欄顯示出來,而POST提交月劈,地址欄不會改變度迂。
傳輸數(shù)據(jù)的大小:
GET提交時猜揪,傳輸數(shù)據(jù)就會受到URL長度限制惭墓,POST由于不是通過URL傳值,理論上書不受限而姐。
安全性:
POST的安全性要比GET的安全性高腊凶;
通過GET提交數(shù)據(jù),用戶名和密碼將明文出現(xiàn)在URL上,比如登陸界面有可能被瀏覽器緩存吭狡。
HTTPS:安全超文本傳輸協(xié)議(Secure Hypertext Transfer Protocol)尖殃,它是一個安全通信通道,基于HTTP開發(fā)划煮,用于客戶計算機和服務(wù)器之間交換信息送丰,使用安全套結(jié)字層(SSI)進行信息交換,即HTTP的安全版弛秋。
7.SDWebImage原理
調(diào)用類別的方法:
從內(nèi)存中(字典)找圖片(當這個圖片在本次程序加載過)器躏,找到直接使用;
從沙盒中找蟹略,找到直接使用登失,緩存到內(nèi)存。
從網(wǎng)絡(luò)上獲取挖炬,使用揽浙,緩存到內(nèi)存,緩存到沙盒意敛。