iOS面試總結(jié)-基礎(chǔ)

[toc]

主要是一些視頻筆記和面試時候常問到的問題記錄。(持續(xù)更新)

為什么要在主線程更新UI

iOS拾遺——為什么必須在主線程操作UI

太長不看版:
UIKit并不是一個 線程安全 的類,UI操作涉及到渲染訪問各種View對象的屬性,如果異步操作下會存在讀寫問題,而為其加鎖則會耗費大量資源并拖慢運行速度。另一方面因為整個程序的起點UIApplication是在主線程進(jìn)行初始化,所有的用戶事件都是在主線程上進(jìn)行傳遞(如點擊、拖動),所以view只能在主線程上才能對事件進(jìn)行響應(yīng)。而在渲染方面由于圖像的渲染需要以60幀的刷新率在屏幕上 同時 更新,在非主線程異步化的情況下無法確定這個處理過程能夠?qū)崿F(xiàn)同步更新。

屬性關(guān)鍵字

讀寫權(quán)限 readonly/readwrite

原子性 atomic/nonatomic

Q:atomic是如何保證線程安全的?
A:atomic只對對象的賦值(setter)和取值(getter)保證線程安全

比如atomic修飾的一個數(shù)組對象,atomic能保證它的賦值和取值是線程安全的,但是如果對數(shù)組進(jìn)行insert或者delete操作,是沒有辦法保證線程安全的

weak和assign的區(qū)別

  1. weak修飾對象,assign可以修飾基礎(chǔ)數(shù)據(jù)類型和對象
  2. weak修飾的對象在釋放之后,指針地址置為nil,而assign修飾的對象在釋放之后,仍然指向原來的指針地址,所以會造成野指針的錯誤
  3. 都不會增加引用計數(shù)

copy

一般用來修飾擁有可變類型的子類的對象,避免在不知情的情況下對對象屬性進(jìn)行了修改
當(dāng)我們用strong來修飾一個NSString屬性的時候,如果賦值的是一個可變對象,當(dāng)可變對象值發(fā)生改變時,屬性也會發(fā)生改變,這不是我們所期待的,因為用strong修飾后,指向跟可變對象相同的一塊內(nèi)存地址,當(dāng)可變對象發(fā)生改變時,屬性也會發(fā)生改變,用copy修飾的話,是深拷貝,會開辟一塊新的內(nèi)存空間,因此可變對象發(fā)生改變是,屬性不會受到影響
示例:https://blog.csdn.net/miaogehehe/article/details/80591805

strong

修飾對象,修飾的對象引用計數(shù)+1,修飾的對象被釋放后,引用計數(shù)-1

KVC

http://www.itdecent.cn/p/9cf76bac1aa6
全稱是Kev-Value Coding 鍵值編碼,可以直接使用字符串訪問對象的屬性

getter

kvc_getter.png
  1. Accessor Method
    會查找訪問器方法是否存在,順序是查找getKey->key->isKey
  2. Instance var
    查找是否有同名的或者類似的實例變量,順序是_key->_isKey->key->isKey
  3. +(BOOL)accessInstanceVariablesDirectly方法的作用
    默認(rèn)返回YES,會去查找實例變量,如果重寫返回NO,則不管存不存在對應(yīng)的實例變量,都不會獲取到實例變量。
  4. valueForUndefinedKey:
    如果沒有找到對應(yīng)的實例變量,那么會調(diào)用valueForUndefinedKey:方法,然后拋出一個NSUndefinedKeyException異常

setter

  1. Setter Method
    查找對應(yīng)的key是否有實現(xiàn)setter方法,按照查找順序為set<Key>:-> _set<Key> -> setIs<Key>
  2. Instance var
    查找方法和getter一樣,如果查找到對應(yīng)的實例變量,直接賦值
  3. +(BOOL)accessInstanceVariablesDirectly同getter的作用
  4. setValue:forUndefinedKey:
    拋出異常NSUndefinedKeyException
    kvc_setter.png

KVO

Q:什么是KVO?
A:
KVO是Objective-C對觀察者設(shè)計模式的一種實現(xiàn)
KVO使用了isa混寫(isa-swizzling)技術(shù)來實現(xiàn)

Q:isa-swizzling在kvo中是怎樣體現(xiàn)的?
當(dāng)我們對一個對象進(jìn)行觀察(addObse…)的時候,系統(tǒng)會在運行時動態(tài)創(chuàng)建一個NSKVONotifying_A的派生類,同時將原來類的isa指針指向這個派生類
派生類重寫setter方法,負(fù)責(zé)通知所有觀察對象(面試的時候,面試官說是通過消息傳遞實現(xiàn)的,具體我沒找到相關(guān)的解釋,有興趣可以自行了解一下,想來應(yīng)該也是,在賦值之前和之后分別都調(diào)用了方法,這不就是發(fā)送消息了嘛)
(在派生類調(diào)用didChangeValueForKey:的時候,runtime會根據(jù)對象的結(jié)構(gòu)和方法列表逐級往上查找到觀察者的監(jiān)聽方法,然后通過消息傳遞的方式將屬性變化的通知傳遞給觀察者)

KVO.png

重寫setter方法


重寫setter.png

Q:kvc能使kvo生效?
A:可以
為什么?
因為set方法已經(jīng)被派生類重寫了,所以會觸發(fā)通知

self super

self
關(guān)鍵字

super
編譯器指令

[self message]和[super message]的實現(xiàn)
其實不管是self還是super真正調(diào)用的對象都是一樣的,只是查找方法的位置不一樣,self是從當(dāng)前類結(jié)構(gòu)體中開始查找,super是從父類中查找,但方法真正的接受者都是當(dāng)前類或者當(dāng)前類的對象

當(dāng)你用[self Class]和[super Class]打印類的時候,打印的都是同一個類,因為他們只是查找方法的位置不同,但是調(diào)用方法的類/對象是一樣的.

Category

Q:你用分類做了什么事情?
A:主要有這幾點:

  • 聲明私有方法
  • 分解體積龐大的類文件
  • 把Framework的私有方法公開

分類的特點

  • 運行時決議,通過runtime把分類當(dāng)中的方法添加到宿主類當(dāng)中
  • 可以為系統(tǒng)類添加分類

分類中可以添加哪些內(nèi)容?

  • 實例方法
  • 類方法
  • 協(xié)議
  • 屬性(沒有添加getter和setter方法)
    在分類的結(jié)構(gòu)體的屬性中可以體現(xiàn)出來(但是有的文章說沒有屬性(instanceProperties)?)
    image.png

如果多個分類實現(xiàn)了同一個方法,執(zhí)行順序是什么?

這個取決于編譯順序,在將分類的方法添加到宿主類的函數(shù)中,有一個倒序遍歷分類方法的while循環(huán),這里最新訪問最后編譯的分類

Q:怎么為Category添加實例變量
A:通過關(guān)聯(lián)對象添加

關(guān)聯(lián)對象的本質(zhì)

關(guān)聯(lián)對象由AssociationManager管理并在AssociationHashMap存儲
所有對象的關(guān)聯(lián)內(nèi)容都在同一個全局容器中

+load、+initialize方法的區(qū)別

+load

1.load方法是在main函數(shù)執(zhí)行前執(zhí)行的
2.子類的+load方法會在它所有父類的+load方法之后執(zhí)行,
3.而分類的+load方法會在它的主類的+load方法之后執(zhí)行,
4.+load方法,它不遵循那套繼承規(guī)則。
5.+load方法調(diào)用順序是:SuperClass -->SubClass --> CategaryClass

+initialize

1.+initialize方法會在類第一次接收到消息時調(diào)用
2.先調(diào)用父類的+initialize,再調(diào)用子類的+initialize
3.如果子類沒有實現(xiàn)+initialize,則會調(diào)用父類的+initialize(父類的+initialize可能會被調(diào)用多次)
如果分類實現(xiàn)了+initialize,會覆蓋類本身的+initialize調(diào)用。

// 該類本身的+initialize調(diào)用實例:
Person 實現(xiàn)了 +initialize
Person(Category) 實現(xiàn)了 +initialize
Teacher : Person 實現(xiàn)了 +initialize

[[Teacher alloc] init]
調(diào)用順序: 
Person(Category) +initialize (Person類的+initialize方法被覆蓋掉了)
Teacher +initialize

Extension

Class Extension在編譯的時候,它的數(shù)據(jù)就已經(jīng)包含在類信息里面了,而Category是在運行時,才會將數(shù)據(jù)合并到類信息中,所以這個時候類結(jié)構(gòu)已經(jīng)確定了,因此不能直接添加成員屬性,但是可以通過associate的全局功能進(jìn)行聲明和定義

CALayer與UIView的關(guān)系?

  • 職責(zé):UIView 負(fù)責(zé)響應(yīng)事件,CALayer 負(fù)責(zé)繪制 UI
    UIView : UIResponder,CALayer : NSObject
    由于CALayer不需要處理交互事件,所以是輕量級的,性能要比UIView高。當(dāng)我們的UIView不需要交互的時候,可以考慮將它替換成CALayer。
  • 關(guān)系:UIView持有一個CALayer屬性,并且是該屬性的代理,UIView的繪制工作是由CALayer完成的

慕課

  • UIView為CALayer提供內(nèi)容,以及負(fù)責(zé)處理觸摸事件,參與響應(yīng)鏈
  • CALayer負(fù)責(zé)顯示內(nèi)容contents
    (單一職責(zé)的體現(xiàn))
    UIView : UIResponder,CALayer : NSObject

事件傳遞 與 視圖響應(yīng)鏈(重點)

事件傳遞
涉及的方法:

// 返回響應(yīng)視圖
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
// 判斷點擊的位置是否在當(dāng)前視圖的范圍內(nèi)
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

事件傳遞流程:

事件傳遞流程

當(dāng)點擊屏幕的時候,事件會傳遞給UIApplication,再由UIApplication傳遞給UIWindow;UIWindow會調(diào)用hitTest:withEvent:方法來返回最終的響應(yīng)視圖。
hitTest:withEvent:內(nèi)部實際調(diào)用了pointInside:withEvent:方法來判斷這個point是否在UIWindow范圍內(nèi);如果在的話,會遍歷子視圖來查找最終響應(yīng)的視圖;遍歷采用的是倒序遍歷,即最后添加到UIWindow上的視圖最優(yōu)先查找,在每一個子視圖UIView中都會調(diào)用hitTest:withEvent:(遞歸),如果最終查找到響應(yīng)視圖,則結(jié)束事件傳遞流程,如果沒有找到,假如事件是在UIWindow的視圖范圍內(nèi),則由UIWindow自己處理。

hitTest方法系統(tǒng)調(diào)用流程

**視圖響應(yīng)鏈


視圖響應(yīng)鏈

涉及的方法(UIResponder的方法):

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;

響應(yīng)鏈其實就是事件傳遞反過來執(zhí)行一遍;首先由當(dāng)前視圖接收事件,如果當(dāng)前視圖沒有處理這個事件,則會傳遞給下一個響應(yīng)者(nextResponder),直到傳遞給UIApplicationDelegate。如果到最后都沒有響應(yīng)者響應(yīng)這個事件的話,那這個事件就丟棄了。

MVC&MVVM

MVC(Model-View-Controller)

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

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

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