1. runloop是來做什么的乙帮?runloop和線程有什么關(guān)系?主線程默認(rèn)開啟了runloop么俏拱?子線程呢暑塑?
RunLoop(消息循環(huán)):說白了就是一種事件監(jiān)聽循環(huán)。就好比是一個(gè)while循環(huán)锅必,監(jiān)聽到事件就起來梯投,沒有就休息。
基本作用:
1.保持程序的持續(xù)運(yùn)行(這也是iOS程序?yàn)槭裁茨芤恢辈粫?huì)死的原因)。
2.處理App中的各種事件(比如觸摸事件分蓖、selector事件、定時(shí)器事件等)尔许。
3.節(jié)省CPU資源么鹤,提高程序性能,有事件就起來味廊,沒有就休息蒸甜。
Runloop與線程:
1.Runloop和線程的關(guān)系:一個(gè)Runloop對應(yīng)著一條唯一的線程。
2.Runloop的創(chuàng)建:主線程Runloop已經(jīng)創(chuàng)建好了余佛,子線程的runloop需要手動(dòng)創(chuàng)建柠新。
3.Runloop的生命周期:在第一次獲取時(shí)創(chuàng)建,在線程結(jié)束時(shí)銷毀辉巡。
參考鏈接:都在說RunLoop...... 到底什么是RunLoop恨憎?
2. runloop的mode是用來做什么的?有幾種mode郊楣?
iOS有五種模式憔恳,
- 其中UIInitializationRunLoopModel應(yīng)用程序啟動(dòng)時(shí)會(huì)使用,啟動(dòng)完成后將不再使用净蚤;
- GSEventReceiveRunLoopMode這個(gè)是接受系統(tǒng)內(nèi)部的Model钥组,通常做不到。
- 還有UITrackingRunLoopMode今瀑、NSDefaultRunLoopMode程梦、NSRunLoopCommonModes三種模式是我們通常用到的,
下文中會(huì)詳細(xì)講解橘荠,其中NSRunLoopCommonModes是一個(gè)占位符屿附,NSDefaultRunLoopMode和UITrackingRunLoopMode都會(huì)綁定這個(gè)占位符。
→ UITrackingRunLoopMode : (優(yōu)先切換!!)這個(gè)模式就是當(dāng)UI事件交互的時(shí)候Runloop切換到的模式@健D昧谩!
場景:這一模式優(yōu)先級最高如蚜,當(dāng)UI事件交互的時(shí)候压恒,都會(huì)優(yōu)先切換到這一模式。
→ NSDefaultRunLoopMode :Runloop的默認(rèn)模式错邦!只要有事件就處理探赫!
場景:默認(rèn)模式,只要有事件就會(huì)自動(dòng)切換到此模式撬呢。
→ NSRunLoopCommonModes :占位符!!(在默認(rèn)下和UITrackingRunLoopMode下B追汀)
場景:這個(gè)主要用在添加一個(gè)NSTimer到RunLoop中。是一個(gè)tag,本質(zhì)上不是一個(gè)Mode,默認(rèn)NSDefaultRunLoopMode和 NSTrackingRunLoopMode都綁定這個(gè)tag。
3. 為什么把NSTimer對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運(yùn)行循環(huán)以后毛仪,滑動(dòng)scrollview的時(shí)候NSTimer卻不動(dòng)了搁嗓?
RunLoop只能運(yùn)行在一種mode下,如果要換mode箱靴,當(dāng)前的loop也需要停下重啟成新的腺逛。利用這個(gè)機(jī)制,ScrollView滾動(dòng)過程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會(huì)切換到UITrackingRunLoopMode來保證ScrollView的流暢滑動(dòng):只能在NSDefaultRunLoopMode模式下處理的事件會(huì)影響scrllView的滑動(dòng)衡怀。
如果我們把一個(gè)NSTimer對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運(yùn)行循環(huán)中的時(shí)候, ScrollView滾動(dòng)過程中會(huì)因?yàn)閙ode的切換棍矛,而導(dǎo)致NSTimer將不再被調(diào)度。
同時(shí)因?yàn)閙ode還是可定制的抛杨,所以:
Timer計(jì)時(shí)會(huì)被scrollView的滑動(dòng)影響的問題可以通過將timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)來解決够委。
4. 蘋果是如何實(shí)現(xiàn)Autorelease Pool的?
autoreleasepool以一個(gè)隊(duì)列數(shù)組的形式實(shí)現(xiàn),主要通過下列三個(gè)函數(shù)完成.
objc_autoreleasepoolPush
objc_autoreleasepoolPop
objc_aurorelease
看函數(shù)名就可以知道怖现,對autorelease分別執(zhí)行push茁帽,和pop操作。銷毀對象時(shí)執(zhí)行release操作真竖。
類結(jié)構(gòu)
1. isa指針脐雪?(對象的isa,類對象的isa恢共,元類的isa都要說)
nil
|
(NSObject)根類對象 isa --> 根類元類 isa
| | |
父類對象 isa --> 父類元類 isa
| |
實(shí)例對象 isa --> 類對象 isa --> 元類 isa
2. 類方法和實(shí)例方法有什么區(qū)別战秋?
- 1.類方法以+號開頭 對象方法以-號開頭
- 2.類方法直接 [類名 類方法名]調(diào)用 對象方法要?jiǎng)?chuàng)建對象后 [對象名 對象方法]調(diào)用
- 3.類方法不能訪問實(shí)例變量 對象方法可以訪問實(shí)例變量
- 4.類方法只能由類來調(diào)用 對象方法只能用對象來調(diào)用
3. 介紹一下分類,能用分類做什么讨韭?內(nèi)部是如何實(shí)現(xiàn)的脂信?它為什么會(huì)覆蓋掉原來的方法?
類別(Category)主要有3個(gè)作用:
- 將類的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中透硝。
- 創(chuàng)建對私有方法的前向引用狰闪。
- 向?qū)ο筇砑臃钦絽f(xié)議。
聲明:@interface 類名(分類名稱) @end
實(shí)現(xiàn):@implementation 類名(分類名稱) @end
注意:
(1)在分類只能增加方法,不能增加成員變量濒生,如果要增加成員變量的話該考慮用繼承去實(shí)現(xiàn)
(2)在分類實(shí)現(xiàn)方法中可以訪問類中的成員變量但是不能訪問類中的屬性@property
(3)在分類中可以重新實(shí)現(xiàn)原類中的方法埋泵,但會(huì)將原類中的方法覆蓋而失效。因?yàn)樵趫?zhí)行對象成員方法的時(shí)候會(huì)優(yōu)先去分類中查找罪治,然后再去原類中去查找丽声,最后去父類中去查找
(4)如果一個(gè)類有多個(gè)分類,而且分類中有同名的方法那么最后編譯的分類會(huì)將前面編譯的分類覆蓋而執(zhí)行輸出
4. 運(yùn)行時(shí)能增加成員變量么觉义?能增加屬性么雁社?如果能,如何增加晒骇?如果不能霉撵,為什么磺浙?
①給NSObject添加分類,在分類中添加屬性徒坡。問題:@property在分類中作用:僅僅是生成get,set方法聲明撕氧,不會(huì)生成get,set方法實(shí)現(xiàn)和下劃線成員屬性,所以要在.m文件實(shí)現(xiàn)setter/getter方法崭参,用static保存下滑線屬性呵曹,這樣一來,當(dāng)對象銷毀時(shí)何暮,屬性無法銷毀
②用runtime動(dòng)態(tài)添加屬性:本質(zhì)是讓屬性與某個(gè)對象產(chǎn)生一段關(guān)聯(lián)
使用場景:給系統(tǒng)的類添加屬性時(shí)
分類 Category 可以添加屬性,不能添加成員變量。分類中是可以為一個(gè)類添加屬性的铐殃,但是一定做不到添加成員變量海洼,Property是Property,Ivar是Ivar富腊。分類里面不能添加Ivar是因?yàn)榉诸惐旧聿⒉皇且粋€(gè)真正的類坏逢,它并沒有自己的ISA。
在Objective-C提供的runtime函數(shù)中赘被,確實(shí)有一個(gè)class_addIvar()函數(shù)用于給類添加成員變量是整,但是閱讀過蘋果的官方文檔的人應(yīng)該會(huì)看到:
This function may only be called after objc_allocateClassPair
and before objc_registerClassPair.
Adding an instance variable to an existing class is not supported.
大概的意思說,這個(gè)函數(shù)只能在“構(gòu)建一個(gè)類的過程中”調(diào)用民假。一旦完成類定義浮入,就不能再添加成員變量了。經(jīng)過編譯的類在程序啟動(dòng)后就被runtime加載羊异,沒有機(jī)會(huì)調(diào)用addIvar事秀。程序在運(yùn)行時(shí)動(dòng)態(tài)構(gòu)建的類需要在調(diào)用objc_registerClassPair之后才可以被使用,同樣沒有機(jī)會(huì)再添加成員變量野舶。
因?yàn)榉椒ê蛯傩圆⒉弧皩儆凇鳖悓?shí)例易迹,而成員變量“屬于”類實(shí)例。我們所說的“類實(shí)例”概念平道,指的是一塊內(nèi)存區(qū)域睹欲,包含了isa指針和所有的成員變量。所以假如允許動(dòng)態(tài)修改類成員變量布局一屋,已經(jīng)創(chuàng)建出的類實(shí)例就不符合類定義了窘疮,變成了無效對象。但方法定義是在objc_class中管理的陆淀,不管如何增刪類方法考余,都不影響類實(shí)例的內(nèi)存布局,已經(jīng)創(chuàng)建出的類實(shí)例仍然可正常使用轧苫。
然而如果在運(yùn)行時(shí)動(dòng)態(tài)生成一個(gè)類楚堤,就可以為其添加成員變量和方法疫蔓。
5. objc中向一個(gè)nil對象發(fā)送消息將會(huì)發(fā)生什么?(返回值是對象身冬,是標(biāo)量衅胀,結(jié)構(gòu)體)
? 如果一個(gè)方法返回值是一個(gè)對象,那么發(fā)送給nil的消息將返回0(nil)酥筝。例如:Person * motherInlaw = [ aPerson spouse] mother]; 如果spouse對象為nil滚躯,那么發(fā)送給nil的消息mother也將返回nil。
? 如果方法返回值為指針類型嘿歌,其指針大小為小于或者等于sizeof(void*)掸掏,float,double宙帝,long double 或者long long的整型標(biāo)量丧凤,發(fā)送給nil的消息將返回0。
? 如果方法返回值為結(jié)構(gòu)體步脓,正如在《Mac OS X ABI 函數(shù)調(diào)用指南》愿待,發(fā)送給nil的消息將返回0。結(jié)構(gòu)體中各個(gè)字段的值將都是0靴患。其他的結(jié)構(gòu)體數(shù)據(jù)類型將不是用0填充的仍侥。
? 如果方法的返回值不是上述提到的幾種情況,那么發(fā)送給nil的消息的返回值將是未定義的鸳君。
相關(guān)閱讀:
1农渊、iOS 面試題 --- 基礎(chǔ)部分
2、iOS 面試題 --- 中級篇 Block
3相嵌、iOS 面試題 --- 中級篇 Runtime
4腿时、iOS 面試題 --- 高級篇