- 猜想runloop內(nèi)部是如何實(shí)現(xiàn)的?
一般來(lái)講邻悬,一個(gè)線程一次只能執(zhí)行一個(gè)任務(wù)随闽,執(zhí)行完成后線程就會(huì)退出。如果我們需要一個(gè)機(jī)制础米,讓線程能隨時(shí)處理事件但并不退出屁桑,通常的代碼邏輯 是這樣的:
function loop() { initialize(); do { var message = get_next_message(); process_message(message); } while (message != quit);}
或使用偽代碼來(lái)展示下:
// // http://weibo.com/luohanchenyilong/ (微博@iOS程序犭袁)// https://github.com/ChenYilongint 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;}
參考鏈接:
《深入理解RunLoop》
摘自博文CFRunLoop须眷,原作者是微博@我就叫Sunny怎么了
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#32-objc使用什么機(jī)制管理對(duì)象內(nèi)存)32. objc使用什么機(jī)制管理對(duì)象內(nèi)存?
通過(guò) retainCount 的機(jī)制來(lái)決定對(duì)象是否需要釋放捕传。 每次 runloop 的時(shí)候庸论,都會(huì)檢查對(duì)象的 retainCount,如果retainCount 為 0聂示,說(shuō)明該對(duì)象沒(méi)有地方需要繼續(xù)使用了鱼喉,可以釋放掉了趋观。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#33-arc通過(guò)什么方式幫助開(kāi)發(fā)者管理內(nèi)存)33. ARC通過(guò)什么方式幫助開(kāi)發(fā)者管理內(nèi)存皱坛?
編譯時(shí)根據(jù)代碼上下文,插入 retain/release
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麦到,這樣做性能更好瓶颠,也是為什么不能在ARC環(huán)境下手動(dòng)retain/release/autorelease,同時(shí)對(duì)同一上下文的同一對(duì)象的成對(duì)retain/release操作進(jìn)行優(yōu)化(即忽略掉不必要的操作)吸祟;ARC也包含運(yùn)行期組件屋匕,這個(gè)地方做的優(yōu)化比較復(fù)雜借杰,但也不能被忽略蔗衡。【TODO:后續(xù)更新會(huì)詳細(xì)描述下】
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#34-不手動(dòng)指定autoreleasepool的前提下一個(gè)autorealese對(duì)象在什么時(shí)刻釋放比如在一個(gè)vc的viewdidload中創(chuàng)建)34. 不手動(dòng)指定autoreleasepool的前提下,一個(gè)autorealese對(duì)象在什么時(shí)刻釋放翩隧?(比如在一個(gè)vc的viewDidLoad中創(chuàng)建)
分兩種情況:手動(dòng)干預(yù)釋放時(shí)機(jī)堆生、系統(tǒng)自動(dòng)去釋放雷酪。
手動(dòng)干預(yù)釋放時(shí)機(jī)--指定autoreleasepool 就是所謂的:當(dāng)前作用域大括號(hào)結(jié)束時(shí)釋放哥力。
系統(tǒng)自動(dòng)去釋放--不手動(dòng)指定autoreleasepool
Autorelease對(duì)象出了作用域之后墩弯,會(huì)被添加到最近一次創(chuàng)建的自動(dòng)釋放池中渔工,并會(huì)在當(dāng)前的 runloop 迭代結(jié)束時(shí)釋放桥温。
釋放的時(shí)機(jī)總結(jié)起來(lái)侵浸,可以用下圖來(lái)表示:
下面對(duì)這張圖進(jìn)行詳細(xì)的解釋?zhuān)?br> 從程序啟動(dòng)到加載完成是一個(gè)完整的運(yùn)行循環(huán)掏觉,然后會(huì)停下來(lái),等待用戶(hù)交互珊燎,用戶(hù)的每一次交互都會(huì)啟動(dòng)一次運(yùn)行循環(huán)悔政,來(lái)處理用戶(hù)所有的點(diǎn)擊事件延旧、觸摸事件迁沫。
我們都是知道: 所有 autorelease 的對(duì)象,在出了作用域之后近弟,會(huì)被自動(dòng)添加到最近創(chuàng)建的自動(dòng)釋放池中祷愉。
但是如果每次都放進(jìn)應(yīng)用程序的 main.m
中的 autoreleasepool 中赦颇,遲早有被撐滿(mǎn)的一刻媒怯。這個(gè)過(guò)程中必定有一個(gè)釋放的動(dòng)作。何時(shí)欺殿?
在一次完整的運(yùn)行循環(huán)結(jié)束之前祈餐,會(huì)被銷(xiāo)毀。
那什么時(shí)間會(huì)創(chuàng)建自動(dòng)釋放池哺壶?運(yùn)行循環(huán)檢測(cè)到事件并啟動(dòng)后山宾,就會(huì)創(chuàng)建自動(dòng)釋放池鳍徽。
子線程的 runloop 默認(rèn)是不工作阶祭,無(wú)法主動(dòng)創(chuàng)建,必須手動(dòng)創(chuàng)建鞭盟。
自定義的 NSOperation 和 NSThread 需要手動(dòng)創(chuàng)建自動(dòng)釋放池齿诉。比如: 自定義的 NSOperation 類(lèi)中的 main 方法里就必須添加自動(dòng)釋放池晌姚。否則出了作用域后挥唠,自動(dòng)釋放對(duì)象會(huì)因?yàn)闆](méi)有自動(dòng)釋放池去處理它,而造成內(nèi)存泄露弧关。
但對(duì)于 blockOperation 和 invocationOperation 這種默認(rèn)的Operation 梯醒,系統(tǒng)已經(jīng)幫我們封裝好了腌紧,不需要手動(dòng)創(chuàng)建自動(dòng)釋放池壁肋。
@autoreleasepool 當(dāng)自動(dòng)釋放池被銷(xiāo)毀或者耗盡時(shí),會(huì)向自動(dòng)釋放池中的所有對(duì)象發(fā)送 release 消息猫胁,釋放自動(dòng)釋放池中的所有對(duì)象弃秆。
如果在一個(gè)vc的viewDidLoad中創(chuàng)建一個(gè) Autorelease對(duì)象髓帽,那么該對(duì)象會(huì)在 viewDidAppear 方法執(zhí)行前就被銷(xiāo)毀了郑藏。
參考鏈接:《黑幕背后的Autorelease》
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#35-bad_access在什么情況下出現(xiàn))35. BAD_ACCESS在什么情況下出現(xiàn)必盖?
訪問(wèn)了野指針,比如對(duì)一個(gè)已經(jīng)釋放的對(duì)象執(zhí)行了release塌忽、訪問(wèn)已經(jīng)釋放對(duì)象的成員變量或者發(fā)消息砚婆。 死循環(huán)
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#36-蘋(píng)果是如何實(shí)現(xiàn)autoreleasepool的)36. 蘋(píng)果是如何實(shí)現(xiàn)autoreleasepool的突勇?
autoreleasepool 以一個(gè)隊(duì)列數(shù)組的形式實(shí)現(xiàn),主要通過(guò)下列三個(gè)函數(shù)完成.
objc_autoreleasepoolPush
objc_autoreleasepoolPop
objc_autorelease
看函數(shù)名就可以知道甲馋,對(duì) autorelease 分別執(zhí)行 push定躏,和 pop 操作。銷(xiāo)毀對(duì)象時(shí)執(zhí)行release操作垮抗。
舉例說(shuō)明:我們都知道用類(lèi)方法創(chuàng)建的對(duì)象都是 Autorelease 的冒版,那么一旦 Person 出了作用域逞姿,當(dāng)在 Person 的 dealloc 方法中打上斷點(diǎn),我們就可以看到這樣的調(diào)用堆棧信息:
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#37-使用block時(shí)什么情況會(huì)發(fā)生引用循環(huán)如何解決)37. 使用block時(shí)什么情況會(huì)發(fā)生引用循環(huán)栋烤,如何解決明郭?
一個(gè)對(duì)象中強(qiáng)引用了block丰泊,在block中又使用了該對(duì)象趁耗,就會(huì)發(fā)射循環(huán)引用。 解決方法是將該對(duì)象使用__weak或者_(dá)_block修飾符修飾之后再在block中使用满葛。
id weak weakSelf = self; 或者 weak __typeof(&*self)weakSelf = self該方法可以設(shè)置宏
id __block weakSelf = self;
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#38-在block內(nèi)如何修改block外部變量)38. 在block內(nèi)如何修改block外部變量嘀韧?
默認(rèn)情況下锄贷,在block中訪問(wèn)的外部變量是復(fù)制過(guò)去的曼月,即:寫(xiě)操作不對(duì)原變量生效哑芹。但是你可以加上__block
來(lái)讓其寫(xiě)操作生效聪姿,示例代碼如下:
__block int a = 0;void (^foo)(void) = ^{ a = 1; }f00(); //這里,a的值被修改為1
參考鏈接:微博@唐巧_boy的著作《iOS開(kāi)發(fā)進(jìn)階》中的第11.2.3章節(jié)
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#39-使用系統(tǒng)的某些block-api如uiview的block版本寫(xiě)動(dòng)畫(huà)時(shí)是否也考慮引用循環(huán)問(wèn)題)39. 使用系統(tǒng)的某些block api(如UIView的block版本寫(xiě)動(dòng)畫(huà)時(shí))破喻,是否也考慮引用循環(huán)問(wèn)題曹质?
系統(tǒng)的某些block api中咆繁,UIView的block版本寫(xiě)動(dòng)畫(huà)時(shí)不需要考慮顶籽,但也有一些api 需要考慮:
所謂“引用循環(huán)”是指雙向的強(qiáng)引用礼饱,所以那些“單向的強(qiáng)引用”(block 強(qiáng)引用 self )沒(méi)有問(wèn)題,比如這些:
[UIView animateWithDuration:duration animations:^{ [self.superview layoutIfNeeded]; }];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.someProperty = xyz; }];
[[NSNotificationCenter defaultCenter] addObserverForName:@"someNotification" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * notification) { self.someProperty = xyz; }];
這些情況不需要考慮“引用循環(huán)”匀伏。
但如果你使用一些參數(shù)中可能含有 ivar 的系統(tǒng) api 够颠,如 GCD 履磨、NSNotificationCenter就要小心一點(diǎn):比如GCD 內(nèi)部如果引用了 self庆尘,而且 GCD 的其他參數(shù)是 ivar驶忌,則要考慮到循環(huán)引用:
__weak typeof(self) weakSelf = self;dispatch_group_async(_operationsGroup, _operationsQueue, ^{typeof(self) strongSelf = weakSelf;[strongSelf doSomething];[strongSelf doSomethingElse];} );
類(lèi)似的:
__weak typeof(self) weakSelf = self; _observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey" object:nil queue:nil usingBlock:^(NSNotification *note) { typeof(self) strongSelf = weakSelf; [strongSelf dismissModalViewControllerAnimated:YES]; }];
self --> _observer --> block --> self 顯然這也是一個(gè)循環(huán)引用付魔。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#40-gcd的隊(duì)列dispatch_queue_t分哪兩種類(lèi)型)40. GCD的隊(duì)列(dispatch_queue_t
)分哪兩種類(lèi)型几苍?
串行隊(duì)列Serial Dispatch Queue
并行隊(duì)列Concurrent Dispatch Queue
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#41-如何用gcd同步若干個(gè)異步調(diào)用如根據(jù)若干個(gè)url異步加載多張圖片然后在都下載完成后合成一張整圖)41. 如何用GCD同步若干個(gè)異步調(diào)用擦剑?(如根據(jù)若干個(gè)url異步加載多張圖片,然后在都下載完成后合成一張整圖)
使用Dispatch Group追加block到Global Group Queue,這些block如果全部執(zhí)行完畢惠勒,就會(huì)執(zhí)行Main Dispatch Queue中的結(jié)束處理的block纠屋。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, queue, ^{ /*加載圖片1 / });dispatch_group_async(group, queue, ^{ /加載圖片2 / });dispatch_group_async(group, queue, ^{ /加載圖片3 */ }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 合并圖片});
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#42-dispatch_barrier_async的作用是什么)42. dispatch_barrier_async
的作用是什么?
在并行隊(duì)列中署辉,為了保持某些任務(wù)的順序岩四,需要等待一些任務(wù)完成后才能繼續(xù)進(jìn)行剖煌,使用 barrier 來(lái)等待之前任務(wù)完成,避免數(shù)據(jù)競(jìng)爭(zhēng)等問(wèn)題桶唐。 dispatch_barrier_async
函數(shù)會(huì)等待追加到Concurrent Dispatch Queue并行隊(duì)列中的操作全部執(zhí)行完之后尤泽,然后再執(zhí)行 dispatch_barrier_async
函數(shù)追加的處理规脸,等 dispatch_barrier_async
追加的處理執(zhí)行結(jié)束之后燃辖,Concurrent Dispatch Queue才恢復(fù)之前的動(dòng)作繼續(xù)執(zhí)行黔龟。
打個(gè)比方:比如你們公司周末跟團(tuán)旅游,高速休息站上巍棱,司機(jī)說(shuō):大家都去上廁所航徙,速戰(zhàn)速?zèng)Q陷虎,上完廁所就上高速尚猿。超大的公共廁所凿掂,大家同時(shí)去,程序猿很快就結(jié)束了踪少,但程序媛就可能會(huì)慢一些,即使你第一個(gè)回來(lái)援奢,司機(jī)也不會(huì)出發(fā)萝究,司機(jī)要等待所有人都回來(lái)后帆竹,才能出發(fā)脓规。 dispatch_barrier_async
函數(shù)追加的內(nèi)容就如同 “上完廁所就上高速”這個(gè)動(dòng)作侨舆。
(注意:使用 dispatch_barrier_async
挨下,該函數(shù)只能搭配自定義并行隊(duì)列 dispatch_queue_t
使用。不能使用:dispatch_get_global_queue
叙淌,否則 dispatch_barrier_async
的作用會(huì)和 dispatch_async
的作用一模一樣鹰霍。 )
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#43-蘋(píng)果為什么要廢棄dispatch_get_current_queue)43. 蘋(píng)果為什么要廢棄dispatch_get_current_queue
茂洒?
dispatch_get_current_queue
容易造成死鎖
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#44-以下代碼運(yùn)行結(jié)果如何)44. 以下代碼運(yùn)行結(jié)果如何瓶竭?
- (void)viewDidLoad{ [super viewDidLoad]; NSLog(@"1"); dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"2"); }); NSLog(@"3");}
只輸出:1 斤贰。發(fā)生主線程鎖死腋舌。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#45-addobserverforkeypathoptionscontext各個(gè)參數(shù)的作用分別是什么observer中需要實(shí)現(xiàn)哪個(gè)方法才能獲得kvo回調(diào))45. addObserver:forKeyPath:options:context:各個(gè)參數(shù)的作用分別是什么,observer中需要實(shí)現(xiàn)哪個(gè)方法才能獲得KVO回調(diào)雌芽?
// 添加鍵值觀察/1 觀察者辨嗽,負(fù)責(zé)處理監(jiān)聽(tīng)事件的對(duì)象2 觀察的屬性3 觀察的選項(xiàng)4 上下文/[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@"Person Name"];
observer中需要實(shí)現(xiàn)一下方法:
// 所有的 kvo 監(jiān)聽(tīng)到事件糟需,都會(huì)調(diào)用此方法/* 1. 觀察的屬性 2. 觀察的對(duì)象 3. change 屬性變化字典(新/舊) 4. 上下文洲押,與監(jiān)聽(tīng)的時(shí)候傳遞的一致 */- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#46-如何手動(dòng)觸發(fā)一個(gè)value的kvo)46. 如何手動(dòng)觸發(fā)一個(gè)value的KVO
所謂的“手動(dòng)觸發(fā)”是區(qū)別于“自動(dòng)觸發(fā)”:
自動(dòng)觸發(fā)是指類(lèi)似這種場(chǎng)景:在注冊(cè) KVO 之前設(shè)置一個(gè)初始值杈帐,注冊(cè)之后,設(shè)置一個(gè)不一樣的值累铅,就可以觸發(fā)了娃兽。
想知道如何手動(dòng)觸發(fā)尽楔,必須知道自動(dòng)觸發(fā) KVO 的原理:
鍵值觀察通知依賴(lài)于 NSObject 的兩個(gè)方法: willChangeValueForKey:
和 didChangevlueForKey:
翔试。在一個(gè)被觀察屬性發(fā)生改變之前垦缅, willChangeValueForKey:
一定會(huì)被調(diào)用,這就 會(huì)記錄舊的值凡恍。而當(dāng)改變發(fā)生后嚼酝, didChangeValueForKey:
會(huì)被調(diào)用竟坛,繼而 observeValueForKey:ofObject:change:context:
也會(huì)被調(diào)用。如果可以手動(dòng)實(shí)現(xiàn)這些調(diào)用洼冻,就可以實(shí)現(xiàn)“手動(dòng)觸發(fā)”了撞牢。
那么“手動(dòng)觸發(fā)”的使用場(chǎng)景是什么叔营?一般我們只在希望能控制“回調(diào)的調(diào)用時(shí)機(jī)”時(shí)才會(huì)這么做屋彪。
具體做法如下:
如果這個(gè) value
是 表示時(shí)間的 self.now
,那么代碼如下:最后兩行代碼缺一不可绒尊。
// .m文件// Created by https://github.com/ChenYilong// 微博@iOS程序犭袁(http://weibo.com/luohanchenyilong/).// 手動(dòng)觸發(fā) value 的KVO畜挥,最后兩行代碼缺一不可。//@property (nonatomic, strong) NSDate *now;- (void)viewDidLoad{ [super viewDidLoad]; [self willChangeValueForKey:@"now"]; // “手動(dòng)觸發(fā)self.now的KVO”垒酬,必寫(xiě)件炉。 [self didChangeValueForKey:@"now"]; // “手動(dòng)觸發(fā)self.now的KVO”勘究,必寫(xiě)。}
但是平時(shí)我們一般不會(huì)這么干斟冕,我們都是等系統(tǒng)去“自動(dòng)觸發(fā)”口糕。“自動(dòng)觸發(fā)”的實(shí)現(xiàn)原理:
比如調(diào)用 setNow:
時(shí)磕蛇,系統(tǒng)還會(huì)以某種方式在中間插入 wilChangeValueForKey:
景描、 didChangeValueForKey:
和observeValueForKeyPath:ofObject:change:context:
的調(diào)用。
大家可能以為這是因?yàn)?setNow:
是合成方法秀撇,有時(shí)候我們也能看到人們這么寫(xiě)代碼:
- (void)setNow:(NSDate *)aDate { [self willChangeValueForKey:@"now"]; // 沒(méi)有必要 _now = aDate; [self didChangeValueForKey:@"now"];// 沒(méi)有必要}
這是完全沒(méi)有必要的代碼超棺,不要這么做,這樣的話呵燕,KVO代碼會(huì)被調(diào)用兩次棠绘。KVO在調(diào)用存取方法之前總是調(diào)用willChangeValueForKey:
,之后總是調(diào)用 didChangeValueForkey:
再扭。怎么做到的呢?答案是通過(guò) isa 混寫(xiě)(isa-swizzling)氧苍。下文《apple用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO?》會(huì)有詳述泛范。
參考鏈接: Manual Change Notification---Apple 官方文檔
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#47-若一個(gè)類(lèi)有實(shí)例變量-nsstring-_foo-調(diào)用setvalueforkey時(shí)可以以foo還是-_foo-作為key)47. 若一個(gè)類(lèi)有實(shí)例變量 NSString *_foo
让虐,調(diào)用setValue:forKey:時(shí),可以以foo還是 _foo
作為key罢荡?
都可以赡突。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#48-kvc的keypath中的集合運(yùn)算符如何使用)48. KVC的keyPath中的集合運(yùn)算符如何使用对扶?
必須用在集合對(duì)象上或普通對(duì)象的集合屬性上
簡(jiǎn)單集合運(yùn)算符有@avg, @count 麸俘, @max 辩稽, @min ,@sum从媚,
格式 @"@sum.age"或 @"集合屬性.@max.age"
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#49-kvc和kvo的keypath一定是屬性么)49. KVC和KVO的keyPath一定是屬性么逞泄?
KVO支持實(shí)例變量
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#50-如何關(guān)閉默認(rèn)的kvo的默認(rèn)實(shí)現(xiàn)并進(jìn)入自定義的kvo實(shí)現(xiàn))50. 如何關(guān)閉默認(rèn)的KVO的默認(rèn)實(shí)現(xiàn),并進(jìn)入自定義的KVO實(shí)現(xiàn)拜效?
請(qǐng)參考:《如何自己動(dòng)手實(shí)現(xiàn) KVO》
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#51-apple用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的kvo)51. apple用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO喷众?
Apple 的文檔對(duì) KVO 實(shí)現(xiàn)的描述:
Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class ...
從Apple 的文檔可以看出:Apple 并不希望過(guò)多暴露 KVO 的實(shí)現(xiàn)細(xì)節(jié)。不過(guò)紧憾,要是借助 runtime 提供的方法去深入挖掘到千,所有被掩蓋的細(xì)節(jié)都會(huì)原形畢露:
當(dāng)你觀察一個(gè)對(duì)象時(shí),一個(gè)新的類(lèi)會(huì)被動(dòng)態(tài)創(chuàng)建赴穗。這個(gè)類(lèi)繼承自該對(duì)象的原本的類(lèi)憔四,并重寫(xiě)了被觀察屬性的 setter 方法。重寫(xiě)的 setter 方法會(huì)負(fù)責(zé)在調(diào)用原 setter 方法之前和之后般眉,通知所有觀察對(duì)象:值的更改了赵。最后通過(guò) isa 混寫(xiě)(isa-swizzling)
把這個(gè)對(duì)象的 isa 指針 ( isa 指針告訴 Runtime 系統(tǒng)這個(gè)對(duì)象的類(lèi)是什么 ) 指向這個(gè)新創(chuàng)建的子類(lèi),對(duì)象就神奇的變成了新創(chuàng)建的子類(lèi)的實(shí)例甸赃。我畫(huà)了一張示意圖柿汛,如下所示:
KVO 確實(shí)有點(diǎn)黑魔法:
Apple 使用了 isa 混寫(xiě)(isa-swizzling)
來(lái)實(shí)現(xiàn) KVO 。
下面做下詳細(xì)解釋?zhuān)?br>
鍵值觀察通知依賴(lài)于 NSObject 的兩個(gè)方法: willChangeValueForKey:
和 didChangevlueForKey:
埠对。在一個(gè)被觀察屬性發(fā)生改變之前络断, willChangeValueForKey:
一定會(huì)被調(diào)用,這就會(huì)記錄舊的值项玛。而當(dāng)改變發(fā)生后貌笨, didChangeValueForKey:
會(huì)被調(diào)用,繼而 observeValueForKey:ofObject:change:context:
也會(huì)被調(diào)用襟沮∽锻铮可以手動(dòng)實(shí)現(xiàn)這些調(diào)用,但很少有人這么做臣嚣。一般我們只在希望能控制回調(diào)的調(diào)用時(shí)機(jī)時(shí)才會(huì)這么做净刮。大部分情況下,改變通知會(huì)自動(dòng)調(diào)用硅则。
比如調(diào)用 setNow:
時(shí)淹父,系統(tǒng)還會(huì)以某種方式在中間插入 wilChangeValueForKey:
、 didChangeValueForKey:
和observeValueForKeyPath:ofObject:change:context:
的調(diào)用怎虫。大家可能以為這是因?yàn)?setNow:
是合成方法暑认,有時(shí)候我們也能看到人們這么寫(xiě)代碼:
- (void)setNow:(NSDate *)aDate { [self willChangeValueForKey:@"now"]; // 沒(méi)有必要 _now = aDate; [self didChangeValueForKey:@"now"];// 沒(méi)有必要}
這是完全沒(méi)有必要的代碼困介,不要這么做,這樣的話蘸际,KVO代碼會(huì)被調(diào)用兩次座哩。KVO在調(diào)用存取方法之前總是調(diào)用willChangeValueForKey:
,之后總是調(diào)用 didChangeValueForkey:
粮彤。怎么做到的呢?答案是通過(guò) isa 混寫(xiě)(isa-swizzling)根穷。第一次對(duì)一個(gè)對(duì)象調(diào)用 addObserver:forKeyPath:options:context:
時(shí),框架會(huì)創(chuàng)建這個(gè)類(lèi)的新的 KVO 子類(lèi)导坟,并將被觀察對(duì)象轉(zhuǎn)換為新子類(lèi)的對(duì)象屿良。在這個(gè) KVO 特殊子類(lèi)中, Cocoa 創(chuàng)建觀察屬性的 setter 惫周,大致工作原理如下:
- (void)setNow:(NSDate *)aDate { [self willChangeValueForKey:@"now"]; [super setValue:aDate forKey:@"now"]; [self didChangeValueForKey:@"now"];}
這種繼承和方法注入是在運(yùn)行時(shí)而不是編譯時(shí)實(shí)現(xiàn)的尘惧。這就是正確命名如此重要的原因。只有在使用KVC命名約定時(shí)递递,KVO才能做到這一點(diǎn)喷橙。
KVO 在實(shí)現(xiàn)中通過(guò) isa 混寫(xiě)(isa-swizzling)
把這個(gè)對(duì)象的 isa 指針 ( isa 指針告訴 Runtime 系統(tǒng)這個(gè)對(duì)象的類(lèi)是什么 ) 指向這個(gè)新創(chuàng)建的子類(lèi),對(duì)象就神奇的變成了新創(chuàng)建的子類(lèi)的實(shí)例登舞。這在Apple 的文檔可以得到印證:
Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class ...
然而 KVO 在實(shí)現(xiàn)中使用了 isa 混寫(xiě)( isa-swizzling)
贰逾,這個(gè)的確不是很容易發(fā)現(xiàn):Apple 還重寫(xiě)、覆蓋了 -class
方法并返回原來(lái)的類(lèi)逊躁。 企圖欺騙我們:這個(gè)類(lèi)沒(méi)有變似踱,就是原本那個(gè)類(lèi)隅熙。稽煤。。
但是囚戚,假設(shè)“被監(jiān)聽(tīng)的對(duì)象”的類(lèi)對(duì)象是 MYClass
酵熙,有時(shí)候我們能看到對(duì) NSKVONotifying_MYClass
的引用而不是對(duì)MYClass
的引用。借此我們得以知道 Apple 使用了 isa 混寫(xiě)(isa-swizzling)
驰坊。具體探究過(guò)程可參考 這篇博文 匾二。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#52-iboutlet連出來(lái)的視圖屬性為什么可以被設(shè)置成weak)52. IBOutlet連出來(lái)的視圖屬性為什么可以被設(shè)置成weak?
參考鏈接: Should IBOutlets be strong or weak under ARC?
文章告訴我們:
因?yàn)榧热挥型怄溎敲匆晥D在xib或者storyboard中肯定存在,視圖已經(jīng)對(duì)它有一個(gè)強(qiáng)引用了微宝。
不過(guò)這個(gè)回答漏了個(gè)重要知識(shí)账蓉,使用storyboard(xib不行)創(chuàng)建的vc良蒸,會(huì)有一個(gè)叫_topLevelObjectsToKeepAliveFromStoryboard的私有數(shù)組強(qiáng)引用所有top level的對(duì)象,所以這時(shí)即便outlet聲明成weak也沒(méi)關(guān)系
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#53-ib中user-defined-runtime-attributes如何使用)53. IB中User Defined Runtime Attributes如何使用分飞?
它能夠通過(guò)KVC的方式配置一些你在interface builder 中不能配置的屬性。當(dāng)你希望在IB中作盡可能多得事情睹限,這個(gè)特性能夠幫助你編寫(xiě)更加輕量級(jí)的viewcontroller
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#54-如何調(diào)試bad_access錯(cuò)誤)54. 如何調(diào)試BAD_ACCESS錯(cuò)誤
重寫(xiě)object的respondsToSelector方法譬猫,現(xiàn)實(shí)出現(xiàn)EXEC_BAD_ACCESS前訪問(wèn)的最后一個(gè)object
通過(guò) Zombie
設(shè)置全局?jǐn)帱c(diǎn)快速定位問(wèn)題代碼所在行
Xcode 7 已經(jīng)集成了BAD_ACCESS捕獲功能:Address Sanitizer讯檐。 用法如下:在配置中勾選?
Enable Address Sanitizer
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8B%EF%BC%89.md#55-lldbgdb常用的調(diào)試命令)55. lldb(gdb)常用的調(diào)試命令?
breakpoint 設(shè)置斷點(diǎn)定位到某一個(gè)函數(shù)
n 斷點(diǎn)指針下一步
po打印對(duì)象
更多 lldb(gdb) 調(diào)試命令可查看
The LLDB Debugger 染服;
蘋(píng)果官方文檔: iOS Debugging Magic 别洪。
Posted by 微博@iOS程序犭袁原創(chuàng)文章,版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0