基礎(chǔ)知識(shí)總結(jié)(一)

最近大雨傾盆,面對(duì)雨夜,心里頓時(shí)思緒萬千。思想自己工作幾年,項(xiàng)目也寫了不少,但是有一些基礎(chǔ)的東西還是懵懵懂懂。需要的時(shí)候才會(huì)去查,去研究。有一些東西一知半解的使用,以至于給自己挖出了好多坑,埋下了好多“暗雷”。一直沒有做一個(gè)系統(tǒng)的整理。剛好最近不是很忙,就借這個(gè)時(shí)期好好的整理一下知識(shí)點(diǎn)。

1.OC為什么是一門動(dòng)態(tài)的語言?

這里先明確一個(gè)詞「動(dòng)態(tài)語言」。什么是動(dòng)態(tài)語言,這個(gè)概念沒有一個(gè)明確的定義。它是一個(gè)程度的度量,就是該語言的runtime到底使用多少bookkeeping的數(shù)據(jù)。Object-C語言是C語言的一個(gè)子類,都知道C語言是一個(gè)靜態(tài)語言。但是Object-C三大特性之一的多態(tài)性讓其擁有了動(dòng)態(tài)性。簡單來說,運(yùn)行時(shí)機(jī)制是我們直到程序運(yùn)行的時(shí)候才去決定一個(gè)對(duì)象的類別,以及調(diào)用該類別對(duì)象指定方法。

Object-C的動(dòng)態(tài)特性的三個(gè)體現(xiàn):動(dòng)態(tài)類型、動(dòng)態(tài)綁定、動(dòng)態(tài)加載

(1)動(dòng)態(tài)類型

簡單來說就是id類型。動(dòng)態(tài)類型跟靜態(tài)類型是相對(duì)的。比如內(nèi)置的的明確的基本類型都屬于靜態(tài)類型(int,NSString等)。靜態(tài)類型在程序編譯的時(shí)候就會(huì)被識(shí)別。所以在程序編譯時(shí)發(fā)現(xiàn)類型不對(duì)應(yīng),Xcode會(huì)發(fā)出警告。而動(dòng)態(tài)類型在程序編譯時(shí)是不能被識(shí)別的,要等到運(yùn)行時(shí)(runtime),才會(huì)根據(jù)語境來識(shí)別。

(2)動(dòng)態(tài)綁定(dynamic binding)

動(dòng)態(tài)綁定只需理解@selector/SEL即可。什么是“函數(shù)”,對(duì)于一些其他的靜態(tài)語言,如C++,C,一般在編譯的時(shí)候就已經(jīng)將要調(diào)用的函數(shù)簽名告訴編譯器了。靜態(tài)的,不可改變。在Object-C中,其實(shí)是沒有函數(shù)的概念的。函數(shù)方法的調(diào)用是通過“消息機(jī)制”來實(shí)現(xiàn)的。調(diào)用一個(gè)實(shí)例的方法,所做的是向該實(shí)例的指針發(fā)送消息。實(shí)例在接收到消息之后,從自身的實(shí)現(xiàn)中尋找響應(yīng)這條消息的方法。Object-C可以先跳過編譯,到運(yùn)行時(shí)在決定再調(diào)用什么方法,需要傳入什么參數(shù),這就是動(dòng)態(tài)綁定。實(shí)現(xiàn)的前提是必須使用SEL變量去綁定一個(gè)方法。最終形成的這個(gè)SEL變量就是代表一個(gè)方法的引用。

注:SEL并不是C里面的函數(shù)指針,SEL只是一個(gè)整數(shù),代表它綁定的那個(gè)方法的編號(hào)ID。@selector()就是獲取類方法的編號(hào)。

(3)動(dòng)態(tài)加載

根據(jù)需求加載所需要的資源。對(duì)于開發(fā)者來說,需要對(duì)不同的機(jī)型進(jìn)行適配。如:在Retina設(shè)備上的加載的是@2x的圖片,在一些老一些的普通屏上加載原圖。

這里有一些有關(guān)于runtime的簡單使用。

2.屬性的實(shí)質(zhì)是什么?包括哪幾個(gè)部分?屬性默認(rèn)的關(guān)鍵字都有哪些?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是用來做什么的?

屬性默認(rèn)的關(guān)鍵字:基本數(shù)據(jù):atomic,readwrite,assign

? ? ? ? ? ? ? ? ? ? ? ? ?普通的OC對(duì)象:atomic,readwrite,strong

(1)@property?

公式表達(dá):ivar + getter + setter 。 @property其實(shí)就是在編譯階段又編譯器為我們自動(dòng)生成ivar成員變量的getter和setter方法。我們?cè)诼暶饕粋€(gè)屬性的時(shí)候,編譯器都做了什么:沒次增加一個(gè)屬性,系統(tǒng)都會(huì)在ivar_list中添加一個(gè)成員變量的描述。在method_list中添加setter和getter方法的描述。在prop_list中增加一個(gè)屬性的描述,計(jì)算該屬性在對(duì)象中的偏移量,然后給出setter和getter方法對(duì)應(yīng)的實(shí)現(xiàn)。在setter方法中從偏移量的位置開始賦值,在getter方法中從偏移量開始取值。為了能夠讀取正確的字節(jié)數(shù),系統(tǒng)對(duì)象偏移量的指針類型進(jìn)行了類型強(qiáng)轉(zhuǎn)。

(2)關(guān)鍵字

readwrite:屬性可讀可寫(屬性聲明的時(shí)候,系統(tǒng)默認(rèn))

readonly:屬性只可以讀取,不可再次賦值,可以獲取

assign:不會(huì)使引用計(jì)數(shù)+1,直接賦值

retain:會(huì)使引用計(jì)數(shù)+1

copy:建立一個(gè)索引計(jì)數(shù)為1的對(duì)象,在賦值的時(shí)使用傳入值的一份拷貝

nonatomic:非原子性訪問,多線程并發(fā)訪問會(huì)提高性能

atomic:原子性訪問

strong:ARC模式下會(huì)使用,相當(dāng)于retain

weak:ARC模式下會(huì)使用,相當(dāng)于assign,可以把對(duì)應(yīng)的指針變量置為nil的狀態(tài)。

(3)@synthesis和@dynamic的作用

@property有兩個(gè)對(duì)應(yīng)的詞,一個(gè)是@synthesis一個(gè)是@dynamic。若兩者都沒有寫,默認(rèn)的就是:

@syntheszie var = _var;

@synthesis的語義是如果你沒有手動(dòng)實(shí)現(xiàn)setter和getter方法,那么編譯器會(huì)自動(dòng)為你加上這兩個(gè)方法

@dynamic告訴編譯器:屬性的setter和getter方法由開發(fā)者自己實(shí)現(xiàn),不需要自動(dòng)生成。(對(duì)于readonly的屬性只需提供getter即可)加入一個(gè)屬性被聲明為

@dynamic var;

然后你也沒有提供@setter和@getter方法,可以通過編譯,但是運(yùn)行的時(shí)候,程序運(yùn)行至

instance.var = someVar

會(huì)因?yàn)槿鄙賡etter方法而crash。同樣如果缺失getter方法,程序運(yùn)行至

someVar = instance.var

時(shí)導(dǎo)致crash。

3.NSString為什么要用copy關(guān)鍵字,如果用strong會(huì)有什么問題?(注意:這里沒有說用strong就一定不行。使用copy和strong是看情況而定的)

因?yàn)楦割愔羔樋梢灾赶蜃宇悓?duì)象,使用copy的目的是為了讓本對(duì)象的屬相不受外界的影響。使用copy無論給我傳入的是一個(gè)可變的對(duì)象或者是一個(gè)不可變對(duì)象,我本身持有的就是一個(gè)不可變的副本。

若使用strong,那么這個(gè)屬性就有可能指向一個(gè)可變對(duì)象。如果這個(gè)可變對(duì)象在外部修改了,那么會(huì)影響該屬性。

4.為什么代理要用weak?week 和 assign 的區(qū)別?block和代理的區(qū)別?

(1)weak修飾代理屬性,指明該對(duì)象并不負(fù)責(zé)保持delegate這個(gè)對(duì)象。delegate這個(gè)對(duì)象的銷毀又外部控制

(2)weak和assign的不同點(diǎn):weak策略在屬性所指的對(duì)象遭到銷毀時(shí),系統(tǒng)會(huì)將weak修飾的屬相對(duì)象的指針置為nil,在OC給nil發(fā)消息是不會(huì)有什么問題的。如果是用assign,在屬性所指的對(duì)象銷毀之后,屬性對(duì)象的指針并為置為nil,造成野指針的存在。這個(gè)時(shí)候再次給此對(duì)象發(fā)送消息,極易造成崩潰問題。assign可以用于修飾非OC對(duì)象,而weak必須勇于OC對(duì)象。

(3)block和代理的區(qū)別:

block更輕型,是用也更簡單,能夠直接訪問上下文,類中不需要存儲(chǔ)臨時(shí)數(shù)據(jù),使用block,代碼連貫,易讀。delegate需要實(shí)現(xiàn)接口,與方法實(shí)現(xiàn)進(jìn)行分離,需要存儲(chǔ)一些臨時(shí)數(shù)據(jù)。代碼比較分離,不易讀。但是可以在很大程度上實(shí)現(xiàn)代碼的解耦。

block根據(jù)使用分類,有三種情形:

a.臨時(shí)性的,只用在棧中,不會(huì)存儲(chǔ)起來

b.需要存儲(chǔ)起來,但只會(huì)調(diào)用一次,或者一個(gè)完成時(shí)期。比如一個(gè)UIView動(dòng)畫,動(dòng)畫完成之后,需要使用block通知外面。一旦調(diào)用block之后,這個(gè)block就可以刪除掉

c.需要存儲(chǔ)起來,可能會(huì)調(diào)用多次。比如按鈕的點(diǎn)擊事件,假如采用block實(shí)現(xiàn),這種block就需要長期存儲(chǔ),并且會(huì)調(diào)用多次。調(diào)用之后block也會(huì)刪除,可能還有下一次按鈕的點(diǎn)擊。

對(duì)于臨時(shí)性的,只在棧中使用的block,沒有循環(huán)引用的問題。block會(huì)自動(dòng)釋放掉。而只調(diào)用一次的block,就需要看內(nèi)部的實(shí)現(xiàn)了。正確的實(shí)現(xiàn)時(shí)block調(diào)用之后,嗎上賦值為空。這樣block也會(huì)釋放掉,同樣也不會(huì)引起循環(huán)引用。

多次調(diào)用的block,極易引起循環(huán)引用,使用時(shí)需要注意。

5.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別?如果是集合是內(nèi)容復(fù)制的話,集合里面的元素也是內(nèi)容復(fù)制么?

淺復(fù)制(shallow copy):在復(fù)制的時(shí)候,對(duì)于被復(fù)制對(duì)象的每一層都是指針復(fù)制

深賦值(one-level-deepcopy):在深復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象,至少有一層時(shí)深復(fù)制

完全復(fù)制(real-deep copy):在完全復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象的每一層都是對(duì)象復(fù)制

非集合類對(duì)象的copy與mutableCopy

[不可變對(duì)象 copy] //淺復(fù)制

[不可變對(duì)象 mutableCopy] //深復(fù)制

[可變對(duì)象 copy] //深復(fù)制

[可變對(duì)象 mutableCopy] //深復(fù)制

類對(duì)象的copy與mutableCopy

[不可變對(duì)象 copy] //淺復(fù)制

[不可變對(duì)象 mutableCopy] //單層深復(fù)制

[可變對(duì)象 copy] //單層深復(fù)制

[可變對(duì)象 mutableCopy] //單層深復(fù)制

需要注意的是集合對(duì)象的內(nèi)容復(fù)制僅限于對(duì)象本身,對(duì)象元素仍然是指針復(fù)制。

6.為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字?

我們將控件拖到Storyboard上,相當(dāng)于創(chuàng)建了一個(gè)對(duì)象,而這個(gè)對(duì)象是加到試圖控制器的view上,存放在view的subviews數(shù)組中。即我們的控件對(duì)象是屬于的view的,view對(duì)其子控件之前的關(guān)系是強(qiáng)引用。當(dāng)我們使用Outlet屬性的時(shí)候,這個(gè)Outlet屬性是有view來進(jìn)行強(qiáng)引用的。我們是在viewController中僅僅對(duì)其進(jìn)行使用,沒有必要擁有它,所以使用weak進(jìn)行修飾。

7.nonatomic和atomic的區(qū)別?atomic是絕對(duì)的線程安全么?為什么?如果不是,那應(yīng)該如何實(shí)現(xiàn)?

nonatomic和atomic用來決定編譯器生成的getter和setter操作是否為原子操作。atomic不是絕對(duì)的線程安全。atomic的本意是指屬性的存取方法是線程安全的,并不保證整個(gè)對(duì)象是線程安全的。如:

聲明一個(gè)NSMutableArray的原子屬性stuff,此時(shí)self.stuff 和 self.stuff = otherstuff都是線程安全的。但是使用[self.stuff objectAtIndex:index]就不是線程安全的。需要用互斥鎖來保證線程安全性。?

8.UICollectionView自定義layout如何實(shí)現(xiàn)?

這篇文章講解的很詳細(xì)

9.用StoryBoard開發(fā)界面有什么弊端?如何避免?

所有的viewController都在同一個(gè)storyboard里進(jìn)行編輯,隨著場(chǎng)景的增加,Xcode打開storyboard的速度會(huì)越來越慢,所有的viewController會(huì)并列在編輯器左側(cè),不方便編輯。無法單獨(dú)調(diào)整每個(gè)場(chǎng)景的生命周期,所有的場(chǎng)景生命周期有storyboard進(jìn)行控制。一旦加載了一個(gè)場(chǎng)景,除非storyboard卸載,否則卸載場(chǎng)景。

優(yōu)化:1>.針對(duì)流程結(jié)構(gòu),可以添加一個(gè)場(chǎng)景流程文檔。

? ? ? ? ? ?2>.純代碼開發(fā)

10.數(shù)據(jù)持久化的幾個(gè)方案

FMDB、Core Data、NSUserDefaults、plist、NSKeyedArchiver(對(duì)象歸解檔)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 把網(wǎng)上的一些結(jié)合自己面試時(shí)遇到的面試題總結(jié)了一下,以后有新的還會(huì)再加進(jìn)來。 1. OC 的理解與特性 OC 作為一...
    AlaricMurray閱讀 2,657評(píng)論 0 20
  • 她是中國著名的建筑學(xué)家和作家,為中國第一代女性建筑學(xué)家,被胡適譽(yù)為中國一代才女。她是中國人民共和國國徽設(shè)計(jì)的...
    章小婷閱讀 765評(píng)論 0 2
  • 有自卑經(jīng)歷的朋友,會(huì)有個(gè)深刻的感受,負(fù)面消極的思想,會(huì)自動(dòng)在大腦中產(chǎn)生,揮之不去。 一般是自我否定、在意他人看法、...
    迎刃閱讀 1,632評(píng)論 5 23
  • 今天,我們先講故事。 第一個(gè)故事。2014年,名校畢業(yè)生石榴和石頭結(jié)婚以后,生了一個(gè)女兒。一家幸福美滿,令人羨慕。...
    彼得貓烏金閱讀 500評(píng)論 0 57
  • 1、人為什么會(huì)感覺到空洞 成長的空洞來自于真實(shí)的自我與渴望的自我之間的差距,這個(gè)差距越大,空洞就越大,內(nèi)心也會(huì)越焦...
    Real_bin閱讀 1,890評(píng)論 0 1

友情鏈接更多精彩內(nèi)容