本人參考GitHub《招聘一個(gè)靠譜的iOS》面試題參考答案(下)
31. runloop的mode作用是什么?
32. 以+ scheduledTimerWithTimeInterval...的方式觸發(fā)的timer垢夹,在滑動(dòng)頁(yè)面上的列表時(shí)感昼,timer會(huì)暫定回調(diào),為什么蚜锨?如何解決?
33. 猜想runloop內(nèi)部是如何實(shí)現(xiàn)的?
34. objc使用什么機(jī)制管理對(duì)象內(nèi)存债查?
35. ARC通過(guò)什么方式幫助開(kāi)發(fā)者管理內(nèi)存?
31. runloop的mode作用是什么瓜挽?
mode主要是用來(lái)指定事件在運(yùn)行循環(huán)中的優(yōu)先級(jí)盹廷,分為4個(gè)狀態(tài):
(1)NSDefaultRunLoopMode(kCFRunLoopDefaultMode):Run的默認(rèn)Mode,通常主線(xiàn)程在這個(gè)mode下運(yùn)行久橙。
(2)UITrackingRunLoopMode:界面追蹤ode俄占,用于UIScrollView追蹤,觸摸滑動(dòng)淆衷,保證界面不受其他Mode影響
(3)UIInitializationRunLoopMode:在剛啟動(dòng)APP時(shí)進(jìn)入的第一個(gè)Mode缸榄,啟動(dòng)完成后就不再使用。(這個(gè)模式主要是蘋(píng)果在用祝拯,開(kāi)發(fā)者用不到)
(4)GSEventReceiveRunLoopMode:接受系統(tǒng)事件的內(nèi)部Mode(繪圖事件)甚带,通常開(kāi)發(fā)者用不到。
(5)NSRunLoopCommonModes(kCFRunLoopCommonModes):這是一個(gè)占位Mode佳头,不是一個(gè)真正的Mode鹰贵。一個(gè)模式可以被標(biāo)記為NSRunLoopCommonModes。
默認(rèn)情況下康嘉,NSDefaultRunLoopMode和UITrackingRunLoopMode被標(biāo)記為NSRunLoopCommonModes碉输,RunLoop在這個(gè)模式下運(yùn)行,則表示RunLoop可以同時(shí)執(zhí)行在NSDefaultRunLoopMode和UITrackingRunLoopMode兩個(gè)模式下亭珍。
應(yīng)用場(chǎng)景舉例:
主線(xiàn)程的RunLoop里有兩個(gè)預(yù)置的Mode:kCFRunLoopDefaultMode和UITrackingRunLoopMode敷钾。這兩個(gè)Mode都已經(jīng)被標(biāo)記為“Common”屬性。DefaultMode是APP平時(shí)所處的狀態(tài)块蚌,TrackingRunLoopMode是追蹤ScrollView滑動(dòng)時(shí)的狀態(tài)闰非。當(dāng)你創(chuàng)建一個(gè)Timer并加到DefaultMode時(shí),Timer會(huì)得到重復(fù)回調(diào)峭范,但此時(shí)滑動(dòng)一個(gè)TableView時(shí)财松,RunLoop會(huì)將mode切換為T(mén)rackingRunLoopMode,這時(shí)Timer就不會(huì)被回調(diào),并且也不會(huì)影響滑動(dòng)操作辆毡。
蘋(píng)果公開(kāi)提供的Mode有兩個(gè):
(1)NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
(2)NSRunLoopCommonModes(kCFRunLoopCommonModes)
32. 以+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block;的方式觸發(fā)的timer菜秦,在滑動(dòng)頁(yè)面上的列表時(shí),timer會(huì)暫筒耙矗回調(diào)球昨,為什么?如何解決眨攘?
RunLoop只能運(yùn)行在一種Mode下主慰,如果要換Mode,當(dāng)前的loop也需需要暫停下重啟成新的鲫售。利用這個(gè)機(jī)制共螺,ScrollView滾動(dòng)過(guò)程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會(huì)切換到UITrackingRunLoopMode來(lái)保證ScrollView的流暢滑動(dòng)。
因此情竹,如果我們把一個(gè)NSTimer對(duì)象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運(yùn)行循環(huán)中的時(shí)候藐不,ScrollView滾動(dòng)過(guò)程中會(huì)因?yàn)镸ode的切換,而導(dǎo)致NSTimer將不再被調(diào)度秦效。
Timer計(jì)時(shí)會(huì)被ScrollView的滑動(dòng)影響的問(wèn)題可以通過(guò)將Timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)來(lái)解決雏蛮。
33. 猜想RunLoop內(nèi)部是如何實(shí)現(xiàn)的?
一般來(lái)講阱州,一個(gè)線(xiàn)程一次只能執(zhí)行一個(gè)任務(wù)挑秉,執(zhí)行完成后線(xiàn)程就會(huì)退出。如果需要一個(gè)機(jī)制贡耽,讓線(xiàn)程能隨時(shí)處理事件但不退出衷模,通常的代碼邏輯是這樣的:
function loop()
{
initialize();
do {
var message = get_next_message();
process_message(message);
} while(message != quit);
}
或者使用偽代碼來(lái)展示下:
int main (int argc, char *argv[])
{
// 程序一直運(yùn)行狀態(tài)
while (AppIsRunning)
{
// 睡眠狀態(tài)鹊汛,等待喚醒事件
id whoWakesMe = SleepForWakingUp();
// 得到喚醒事件
id event = GetEvent(whoWakesMe);
// 開(kāi)始處理事件
HandleEvent(event);
}
return 0;
}
34. objc使用什么機(jī)制管理對(duì)象內(nèi)存蒲赂?
objc通過(guò)retainCount(引用計(jì)數(shù)器)的機(jī)制來(lái)決定對(duì)象是否需要釋放。每次runloop的時(shí)候都會(huì)檢查對(duì)象的retainCount刁憋,如果retainCount為0滥嘴,說(shuō)明該對(duì)象沒(méi)有地方繼續(xù)使用了,可以釋放掉了至耻。
35. ARC通過(guò)什么方式幫助開(kāi)發(fā)者管理內(nèi)存若皱?
ARC相對(duì)于MRC,不是在編譯時(shí)添加retain/release/autorelease這么簡(jiǎn)單尘颓。應(yīng)該是編譯器和運(yùn)行期兩部分共同幫助開(kāi)發(fā)者管理內(nèi)存走触。
在編譯器,ARC用的是更底層的C接口實(shí)現(xiàn)的retain/release/autorelease疤苹,這樣做性能更好互广,也是為什么不能在A(yíng)RC環(huán)境下手動(dòng)retain/release/autorelease,同時(shí)對(duì)同一上下文的同一對(duì)象的成對(duì)retain/release操作進(jìn)行優(yōu)化(即忽略不必要的操作);ARC也包含運(yùn)行期的組件惫皱。