主要的幾個(gè)大模塊
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之前對(duì)局部變量進(jìn)行修改,在調(diào)用Block時(shí)局部變量值是修改之前的舊值;在Block中不可以直接修改局部變量。
__block修飾的局部變量? 就可以
全局變量 就可以
static靜態(tài)變量? 就可以
三、
? ? ? 如果對(duì)象內(nèi)部有一個(gè)Block屬性,而在Block內(nèi)部又訪問了該對(duì)象,那么會(huì)造成循環(huán)引用,解決循環(huán)引用的辦法是使用一個(gè)弱引用的指針指向該對(duì)象,然后在Block內(nèi)部使用該弱引用指針來進(jìn)行操作,這樣避免了Block對(duì)對(duì)象進(jìn)行強(qiáng)引用
?談?wù)刡lock使用時(shí)的注意點(diǎn)?
1、在block內(nèi)部使用外部指針且會(huì)造成循環(huán)引用情況下,需要用__weak修飾外部指針__weak typeof(self) weakSelf = self;
2、在block內(nèi)部如果調(diào)用了延時(shí)函數(shù)還使用弱指針會(huì)取不到該指針,因?yàn)橐呀?jīng)被銷毀了,需要在block內(nèi)部再將弱指針重新強(qiáng)引用一下__strong typeof(self) strongSelf = weakSelf;
3、如果需要在block內(nèi)部改變外部變量的話,需要在用__block修飾外部變量
?在Block中如何修改Block外部變量的值
我們最常見的做法就是在需要修改的變量前加上 __block 修飾
*解釋:很多時(shí)候,我們都直接這樣去操作,但是為什么加上__block之后,就可以這樣操作?
在內(nèi)存中分區(qū)大致可分為:
棧:用于存放臨時(shí)變量,處理速度快,但是因?yàn)闂?nèi)存極小,容易產(chǎn)生內(nèi)存泄漏
堆:空間大,處理速度一般
只讀數(shù)據(jù)段:用于存放常量(字面常量,符號(hào)常量),不能被修改
數(shù)據(jù)段:全部變量
代碼段:代碼,函數(shù)名等
通過上面的分區(qū)我們可以知道
變量聲明出來存放在棧上面
而block,默認(rèn)存放在NSGlobalBlock 全局的block;我們常常把block和C中的函數(shù)做對(duì)比,此時(shí)也類似,NSGlobalBlock類似于函數(shù),存放在代碼段
當(dāng)block內(nèi)部使用了外部的變量時(shí),block的存放位置變成了NSMallockBlock(堆)
__block 修飾以后,會(huì)類似于橋接,將被修飾的變量被block所持有,此時(shí)該變量也轉(zhuǎn)存到堆空間,所以此時(shí)Block內(nèi)部就可以對(duì)外部的變量進(jìn)行修改
2.運(yùn)行時(shí)機(jī)制-Runtime
runtime庫里面包含了跟類、成員變量、方法相關(guān)的API,比如獲取類里面的所有成員變量,為類動(dòng)態(tài)添加成員變量,動(dòng)態(tài)改變類的方法實(shí)現(xiàn),為類動(dòng)態(tài)添加新的方法等 需要導(dǎo)入
1.是什么
1> runtime是一套比較底層的純C語言API, 屬于1個(gè)C語言庫, 包含了很多底層的C語言API
2> 平時(shí)編寫的OC代碼, 在程序運(yùn)行過程中, 其實(shí)最終都是轉(zhuǎn)成了runtime的C語言代碼, runtime算是OC的幕后工作者
3> 舉例: OC : [[MJPerson alloc] init]
runtime : objc_msgSend(objc_msgSend("MJPerson" , "alloc"), "init")
2.用過么? 怎么用?
1> runtime是屬于OC的底層, 可以進(jìn)行一些非常底層的操作(用OC是無法現(xiàn)實(shí)的, 不好實(shí)現(xiàn)) * 在程序運(yùn)行過程中, 動(dòng)態(tài)創(chuàng)建一個(gè)類(比如KVO的底層實(shí)現(xiàn)) * 在程序運(yùn)行過程中, 動(dòng)態(tài)地為某個(gè)類添加屬性方法, 修改屬性值方法 * 遍歷一個(gè)類的所有成員變量(屬性)所有方法
3.相關(guān)的頭文件
? ? ? 1> 頭文件
? ? ? 2> 相關(guān)應(yīng)用
* NSCoding(歸檔和解檔, 利用runtime遍歷模型對(duì)象的所有屬性)
* 字典 --> 模型 (利用runtime遍歷模型對(duì)象的所有屬性, 根據(jù)屬性名從字典中取出對(duì)應(yīng)的值, 設(shè)置到模型的屬性上)
* KVO(利用runtime動(dòng)態(tài)產(chǎn)生一個(gè)類)
* 用于封裝框架(想怎么改就怎么改)
3> 相關(guān)函數(shù)
* objc_msgSend : 給對(duì)象發(fā)送消息
* class_copyMethodList : 遍歷某個(gè)類所有的方法
* class_copyIvarList : 遍歷某個(gè)類所有的成員變量
* class_.....
3.Runloop
RunLoop,是多線程的法寶,即一個(gè)線程一次只能執(zhí)行一個(gè)任務(wù),執(zhí)行完任務(wù)后就會(huì)退出線程。主線程執(zhí)行完即時(shí)任務(wù)時(shí)會(huì)繼續(xù)等待接收事件而不退出。非主線程通常來說就是為了執(zhí)行某一任務(wù)的,執(zhí)行完畢就需要?dú)w還資源,因此默認(rèn)是不運(yùn)行RunLoop的;
每一個(gè)線程都有其對(duì)應(yīng)的RunLoop,只是默認(rèn)只有主線程的RunLoop是啟動(dòng)的,其它子線程的RunLoop默認(rèn)是不啟動(dòng)的,若要啟動(dòng)則需要手動(dòng)啟動(dòng);
在一個(gè)單獨(dú)的線程中,如果需要在處理完某個(gè)任務(wù)后不退出,繼續(xù)等待接收事件,則需要啟用RunLoop;
NSRunLoop提供了一個(gè)添加NSTimer的方法,可以指定Mode,如果要讓任何情況下都回調(diào),則需要設(shè)置Mode為Common模式;
實(shí)質(zhì)上,對(duì)于子線程的runloop默認(rèn)是不存在的,因?yàn)樘O果采用了懶加載的方式。如果我們沒有手動(dòng)調(diào)用[NSRunLoop currentRunLoop]的話,就不會(huì)去查詢是否存在當(dāng)前線程的RunLoop,也就不會(huì)去加載,更不會(huì)創(chuàng)建。
4.多線程
NSThread:當(dāng)需要進(jìn)行一些耗時(shí)操作時(shí)會(huì)把耗時(shí)的操作放到線程中。線程同步:多個(gè)線程同時(shí)訪問一個(gè)數(shù)據(jù)會(huì)出問題,NSlock、線程同步塊、@synchronized(self){}。
NSOperationQueue操作隊(duì)列(不需考慮線程同步問題)。編程的重點(diǎn)都放在main里面,NSInvocationOperation、BSBlockOperation、自定義Operation。創(chuàng)建一個(gè)操作綁定相應(yīng)的方法,當(dāng)把操作添加到操作隊(duì)列中時(shí),操作綁定的方法就會(huì)自動(dòng)執(zhí)行了,當(dāng)把操作添加到操作隊(duì)列中時(shí),默認(rèn)會(huì)調(diào)用main方法。
GCD(``Grand Central Dispatch`)宏大的中央調(diào)度,串行隊(duì)列、并發(fā)隊(duì)列、主線程隊(duì)列;
同步和異步:同步指第一個(gè)任務(wù)不執(zhí)行完,不會(huì)開始第二個(gè),異步是不管第一個(gè)有沒有執(zhí)行完,都開始第二個(gè)。
串行和并行:串行是多個(gè)任務(wù)按一定順序執(zhí)行,并行是多個(gè)任務(wù)同時(shí)執(zhí)行;
代碼是在分線程執(zhí)行,在主線程嘟列中刷新UI。
** 多線程編程是防止主線程堵塞、增加運(yùn)行效率的最佳方法。**
Apple提供了NSOperation這個(gè)類,提供了一個(gè)優(yōu)秀的多線程編程方法;
一個(gè)NSOperationQueue操作隊(duì)列,相當(dāng)于一個(gè)線程管理器,而非一個(gè)線程,因?yàn)槟憧梢栽O(shè)置這個(gè)線程管理器內(nèi)可以并行運(yùn)行的線程數(shù)量等。
多線程是一個(gè)比較輕量級(jí)的方法來實(shí)現(xiàn)單個(gè)應(yīng)用程序內(nèi)多個(gè)代碼執(zhí)行路徑。
iPhoneOS下的主線程的堆棧大小是1M。第二個(gè)線程開始就是512KB,并且該值不能通過編譯器開關(guān)或線程API函數(shù)來更改,只有主線程有直接修改UI的能力。
?線程與進(jìn)程的區(qū)別和聯(lián)系?
進(jìn)程和線程都是由操作系統(tǒng)所體會(huì)的程序運(yùn)行的基本單元,系統(tǒng)利用該基本單元實(shí)現(xiàn)系統(tǒng)對(duì)應(yīng)用的并發(fā)性。
程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比=多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。
5.內(nèi)存的使用和優(yōu)化的注意事項(xiàng)
重用問題:如UITableViewCells、UICollectionViewCells、UITableViewHeaderFooterViews設(shè)置正確的reuseIdentifier,充分重用;
盡量把views設(shè)置為不透明:當(dāng)opque為NO的時(shí)候,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果,可提高性能;
不要使用太復(fù)雜的XIB/Storyboard:載入時(shí)就會(huì)將XIB/storyboard需要的所有資源,包括圖片全部載入內(nèi)存,即使未來很久才會(huì)使用。那些相比純代碼寫的延遲加載,性能及內(nèi)存就差了很多;
選擇正確的數(shù)據(jù)結(jié)構(gòu):學(xué)會(huì)選擇對(duì)業(yè)務(wù)場(chǎng)景最合適的數(shù)組結(jié)構(gòu)是寫出高效代碼的基礎(chǔ)。比如,數(shù)組: 有序的一組值。使用索引來查詢很快,使用值查詢很慢,插入/刪除很慢。字典: 存儲(chǔ)鍵值對(duì),用鍵來查找比較快。集合: 無序的一組值,用值來查找很快,插入/刪除很快。
gzip/zip壓縮:當(dāng)從服務(wù)端下載相關(guān)附件時(shí),可以通過gzip/zip壓縮后再下載,使得內(nèi)存更小,下載速度也更快。
延遲加載:對(duì)于不應(yīng)該使用的數(shù)據(jù),使用延遲加載方式。對(duì)于不需要馬上顯示的視圖,使用延遲加載方式。比如,網(wǎng)絡(luò)請(qǐng)求失敗時(shí)顯示的提示界面,可能一直都不會(huì)使用到,因此應(yīng)該使用延遲加載。
數(shù)據(jù)緩存:對(duì)于cell的行高要緩存起來,使得reload數(shù)據(jù)時(shí),效率也極高。而對(duì)于那些網(wǎng)絡(luò)數(shù)據(jù),不需要每次都請(qǐng)求的,應(yīng)該緩存起來,可以寫入數(shù)據(jù)庫,也可以通過plist文件存儲(chǔ)。
處理內(nèi)存警告:一般在基類統(tǒng)一處理內(nèi)存警告,將相關(guān)不用資源立即釋放掉
重用大開銷對(duì)象:一些objects的初始化很慢,比如NSDateFormatter和NSCalendar,但又不可避免地需要使用它們。通常是作為屬性存儲(chǔ)起來,防止反復(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í)變量處理數(shù)據(jù)時(shí),自動(dòng)釋放池以保證能及時(shí)釋放內(nèi)存;
6.網(wǎng)絡(luò)
?TCP和UDP的區(qū)別于聯(lián)系
TCP為傳輸控制層協(xié)議,為面向連接、可靠的、點(diǎn)到點(diǎn)的通信;
UDP為用戶數(shù)據(jù)報(bào)協(xié)議,非連接的不可靠的點(diǎn)到多點(diǎn)的通信;
TCP側(cè)重可靠傳輸,UDP側(cè)重快速傳輸。
?TCP連接的三次握手
第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到syn包,必須確認(rèn)客戶的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)SYN包,即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN+RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次狀態(tài)。
?Scoket連接和HTTP連接的區(qū)別:
HTTP協(xié)議是基于TCP連接的,是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。Socket是對(duì)TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個(gè)調(diào)用接口(API),通過Socket,我們才能使用TCP/IP協(xié)議。
HTTP連接:短連接,客戶端向服務(wù)器發(fā)送一次請(qǐng)求,服務(wù)器響應(yīng)后連接斷開,節(jié)省資源。服務(wù)器不能主動(dòng)給客戶端響應(yīng)(除非采用HTTP長(zhǎng)連接技術(shù)),iPhone主要使用類NSURLConnection。
Socket連接:長(zhǎng)連接,客戶端跟服務(wù)器端直接使用Socket進(jìn)行連接,沒有規(guī)定連接后斷開,因此客戶端和服務(wù)器段保持連接通道,雙方可以主動(dòng)發(fā)送數(shù)據(jù),一般多用于游戲.Socket默認(rèn)連接超時(shí)時(shí)間是30秒,默認(rèn)大小是8K(理解為一個(gè)數(shù)據(jù)包大?。?/p>
?HTTP協(xié)議的特點(diǎn),關(guān)于HTTP請(qǐng)求GET和POST的區(qū)別
?GET和POST的區(qū)別:
HTTP超文本傳輸協(xié)議,是短連接,是客戶端主動(dòng)發(fā)送請(qǐng)求,服務(wù)器做出響應(yīng),服務(wù)器響應(yīng)之后,鏈接斷開。HTTP是一個(gè)屬于應(yīng)用層面向?qū)ο蟮膮f(xié)議,HTTP有兩類報(bào)文:請(qǐng)求報(bào)文和響應(yīng)報(bào)文。
HTTP請(qǐng)求報(bào)文:一個(gè)HTTP請(qǐng)求報(bào)文由請(qǐng)求行、請(qǐng)求頭部、空行和請(qǐng)求數(shù)據(jù)4部分組成。
HTTP響應(yīng)報(bào)文:由三部分組成:狀態(tài)行、消息報(bào)頭、響應(yīng)正文。
GET請(qǐng)求:參數(shù)在地址后拼接,沒有請(qǐng)求數(shù)據(jù),不安全(因?yàn)樗袇?shù)都拼接在地址后面),不適合傳輸大量數(shù)據(jù)(長(zhǎng)度有限制,為1024個(gè)字節(jié))。
GET提交、請(qǐng)求的數(shù)據(jù)會(huì)附在URL之后,即把數(shù)據(jù)放置在HTTP協(xié)議頭中。? 以?分割URL和傳輸數(shù)據(jù),多個(gè)參數(shù)用&連接。如果數(shù)據(jù)是英文字母或數(shù)字,原樣發(fā)送,? 如果是空格,轉(zhuǎn)換為+,如果是中文/其他字符,則直接把字符串用BASE64加密。
POST請(qǐng)求:參數(shù)在請(qǐng)求數(shù)據(jù)區(qū)放著,相對(duì)GET請(qǐng)求更安全,并且數(shù)據(jù)大小沒有限制。把提交的數(shù)據(jù)放置在HTTP包的包體中.
GET提交的數(shù)據(jù)會(huì)在地址欄顯示出來,而POST提交,地址欄不會(huì)改變。
傳輸數(shù)據(jù)的大?。?/p>
GET提交時(shí),傳輸數(shù)據(jù)就會(huì)受到URL長(zhǎng)度限制,POST由于不是通過URL傳值,理論上書不受限。
安全性:
POST的安全性要比GET的安全性高;
通過GET提交數(shù)據(jù),用戶名和密碼將明文出現(xiàn)在URL上,比如登陸界面有可能被瀏覽器緩存。
HTTPS:安全超文本傳輸協(xié)議(Secure Hypertext Transfer Protocol),它是一個(gè)安全通信通道,基于HTTP開發(fā),用于客戶計(jì)算機(jī)和服務(wù)器之間交換信息,使用安全套結(jié)字層(SSI)進(jìn)行信息交換,即HTTP的安全版。
7.SDWebImage原理
調(diào)用類別的方法:
從內(nèi)存中(字典)找圖片(當(dāng)這個(gè)圖片在本次程序加載過),找到直接使用;
從沙盒中找,找到直接使用,緩存到內(nèi)存。
從網(wǎng)絡(luò)上獲取,使用,緩存到內(nèi)存,緩存到沙盒。