1.如何理解interface 和 property?
答:a. 只在@interface中定義變量的話,你所定義的變量只能在當(dāng)前的類中訪問,在其他類中是訪問不了的引矩;而用@property聲明的變量可以在外部訪問烧给。
b.用了@property去聲明的變量燕偶,可以使用“self.變量名”的方式去讀寫變量。而用@interface的方式就不可以础嫡。
2.怎么內(nèi)存管理(ARC)
a. block的內(nèi)存管理
iOS中使用block必須自己管理內(nèi)存指么,錯(cuò)誤的內(nèi)存管理將導(dǎo)致循環(huán)引用等內(nèi)存泄漏問題,這里主要說明在ARC下block聲明和使用的時(shí)候需要注意的兩點(diǎn): 1)如果你使用@property去聲明一個(gè)block的時(shí)候榴鼎,一般使用copy來進(jìn)行修飾(當(dāng)然也可以不寫伯诬,編譯器自動(dòng)進(jìn)行copy操作),盡量不要使用retain巫财。
@property (nonatomic, copy) void(^block)(NSData * data);
2)block會(huì)對(duì)內(nèi)部使用的對(duì)象進(jìn)行強(qiáng)引用盗似,因此在使用的時(shí)候應(yīng)該確定不會(huì)引起循環(huán)引用,當(dāng)然保險(xiǎn)的做法就是添加弱引用標(biāo)記平项。
__weak typeof(self) weakSelf = self;
有興趣的讀者可以深入了解:
1赫舒、block的內(nèi)部實(shí)現(xiàn)原理是什么? 2葵礼、從內(nèi)存位置來看block有幾種類型号阿?它們的內(nèi)存管理方式各是怎樣的? 3、對(duì)于不同類型的外部變量,block的內(nèi)存管理都是怎樣的废菱?
b 經(jīng)典內(nèi)存泄漏及其解決方案
雖然ARC好處多多乖菱,然而也并無法避免內(nèi)存泄漏問題,下面介紹在ARC中常見的內(nèi)存泄漏。
b.1 僵尸對(duì)象和野指針
僵尸對(duì)象:內(nèi)存已經(jīng)被回收的對(duì)象。
野指針:指向僵尸對(duì)象的指針,向野指針發(fā)送消息會(huì)導(dǎo)致崩潰湖雹。
野指針錯(cuò)誤形式在Xcode中通常表現(xiàn)為:Thread 1:EXC_BAD_ACCESS,因?yàn)槟阍L問了一塊已經(jīng)不屬于你的內(nèi)存曙搬∷だ簦 例子代碼:(沒有出現(xiàn)錯(cuò)誤的筒子多運(yùn)行幾遍,因?yàn)楂@取野指針指向的結(jié)果是不確定的)
Dog * dog = [[Dog alloc]init]; NSLog(@"before"); NSLog(@"%s",object_getClassName(dog)); [dog release]; NSLog(@"after"); NSLog(@"%s",object_getClassName(dog));
運(yùn)行結(jié)果:
[15184:5811062] before [15184:5811062] Dog [15184:5811062] after (lldb)
可以看到纵装,當(dāng)運(yùn)行到第六行的時(shí)候崩潰了征讲,并給出了EXC_BAD_ACCESS的提示。
解決方案:
對(duì)象已經(jīng)被釋放后橡娄,應(yīng)將其指針置為空指針(沒有指向任何對(duì)象的指針诗箍,給空指針發(fā)送消息不會(huì)報(bào)錯(cuò))。
然而在實(shí)際開發(fā)中實(shí)際遇到EXC_BAD_ACCESS錯(cuò)誤時(shí)挽唉,往往很難定位到錯(cuò)誤點(diǎn)滤祖,幸好Xcode提供方便的工具給我們來定位及分析錯(cuò)誤筷狼。 1)在product-scheme-edit scheme-diagnostics中將enable zombie objects勾選上匠童,下次再出現(xiàn)這樣的錯(cuò)誤就可以準(zhǔn)確定位了埂材。 運(yùn)行結(jié)果:
[15169:5801945] before [15169:5801945] Dog [15169:5801945] after [15169:5801945] _NSZombie_Dog
可以看到俏让,當(dāng)運(yùn)行到第六行時(shí)并沒有崩潰楞遏,并給出了NSZombie的提示茬暇。
2)在Xcode-open developer tool-Instruments打開工具集首昔,選擇Zombies工具可以對(duì)已安裝的應(yīng)用進(jìn)行僵尸對(duì)象檢測。
b.2 循環(huán)引用
循環(huán)引用是ARC中最常出現(xiàn)的問題糙俗,對(duì)于可能引發(fā)循環(huán)引用的一些原因在前一篇文章iOS總結(jié)篇:影響控制器正常釋放的常見問題中有提及勒奇,大家可以看看。
一般來講循環(huán)引用也是可以使用工具來檢測到的巧骚,分為兩種: 1)在product-Analyze中使用靜態(tài)分析來檢測代碼中可能存在循環(huán)引用的問題赊颠。
2)在Xcode-open developer tool-Instruments打開工具集,選擇Leaks工具可以對(duì)已安裝的應(yīng)用進(jìn)行內(nèi)存泄漏檢測劈彪,此工具能檢測靜態(tài)分析不會(huì)提示竣蹦,但是到運(yùn)行時(shí)才會(huì)出現(xiàn)的內(nèi)存泄漏問題。
Leaks工具雖然強(qiáng)大沧奴,但是它不能檢測到block循環(huán)引用導(dǎo)致的內(nèi)存泄漏痘括,這種情況一般需要自行排查問題(考驗(yàn)?zāi)愕幕竟r(shí)候到了),傻瓜式的方案當(dāng)然是重寫對(duì)象的dealloc方法來監(jiān)測對(duì)象是否正常釋放滔吠,來確認(rèn)沒有形成循環(huán)引用纲菌。
由于ARC中循環(huán)引用出現(xiàn)的幾率相對(duì)較大,很多大神或者團(tuán)隊(duì)都提供了很多解決此問題的思路和方法疮绷,甚至開發(fā)了插件和類庫來幫助開發(fā)者更好地檢測問題翰舌,有興趣的讀者可以研究一下,是否好用冬骚,孰好孰壞就由讀者自行評(píng)判了椅贱。
b.3 循環(huán)中對(duì)象占用內(nèi)存大
這個(gè)問題常見于循環(huán)次數(shù)較大,循環(huán)體生成的對(duì)象占用內(nèi)存較大的情景只冻”勇螅 例子代碼:我需要10000個(gè)演員來打仗
for (int i = 0; i < 10000; i ++) { Person * soldier = [[Person alloc]init]; [soldier fight]; }
該循環(huán)內(nèi)產(chǎn)生大量的臨時(shí)對(duì)象,直至循環(huán)結(jié)束才釋放属愤,可能導(dǎo)致內(nèi)存泄漏女器,解決方法和上文中提到的自動(dòng)釋放池常見問題類似:在循環(huán)中創(chuàng)建自己的autoReleasePool,及時(shí)釋放占用內(nèi)存大的臨時(shí)變量住诸,減少內(nèi)存占用峰值驾胆。
for (int i = 0; i < 10000; i ++) { @autoreleasepool { Person * soldier = [[Person alloc]init]; [soldier fight]; } }
然而有時(shí)候autoReleasePool也不是萬能的: 例子:假如有2000張圖片涣澡,每張1M左右,現(xiàn)在需要獲取所有圖片的尺寸丧诺,你會(huì)怎么做入桂? 如果這樣做
for (int i = 0; i < 2000; i ++) { CGSize size = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]].size; //add size to array }
用imageNamed方法加載圖片占用Cache的內(nèi)存,autoReleasePool也不能釋放驳阎,對(duì)此問題需要另外的解決方法抗愁,當(dāng)然保險(xiǎn)的當(dāng)然是雙管齊下了
for (int i = 0; i < 2000; i ++) { @autoreleasepool { CGSize size = [UIImage imageWithContentsOfFile:filePath].size; //add siez to array } }
b.4 無限循環(huán)
這個(gè)是比4.3更極端的情況,無論你出于什么原因呵晚,當(dāng)你啟動(dòng)了一個(gè)無限循環(huán)的時(shí)候蜘腌,ARC會(huì)默認(rèn)該方法用不會(huì)執(zhí)行完畢,方法里面的對(duì)象就永不釋放饵隙,內(nèi)存無限上漲撮珠,導(dǎo)致內(nèi)存泄漏〗鹈 例子:
NSLog(@"start !"); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ BOOL isSucc = YES; while (isSucc) { [NSThread sleepForTimeInterval:1.0]; NSLog(@"create an obj"); } });
輸出結(jié)果為
[7026:3555827] start ! [7026:3556236] create an obj [7026:3556236] create an obj [7026:3556236] create an obj [7026:3556236] create an obj [7026:3555827] dealloc [7026:3556236] create an obj [7026:3556236] create an obj [7026:3556236] create an obj
可以看到芯急,當(dāng)控制器釋放后該循環(huán)還在繼續(xù)∈豢。
對(duì)于這類問題解決方案是什么呢娶耍?留給讀者思考吧~ _
提示:解決方法有autoreleasepool、block饼酿、timer等等
3.cocoa框架中有什么設(shè)計(jì)模式榕酒?
a.單例模式
b.觀察者模式:KVO機(jī)制 通知機(jī)制 委托模式
http://www.cocoachina.com/ios/20141111/10187.html
1.如何定位自己位置?
2.如何實(shí)現(xiàn)下拉加載更多數(shù)據(jù)嗜湃?
3.關(guān)于GCD
兩個(gè)重要概念:隊(duì)列 和 任務(wù)的奈应、和 隊(duì)列組
隊(duì)列:串行隊(duì)列、并行隊(duì)列购披、主隊(duì)列杖挣、全局隊(duì)列
任務(wù):同步執(zhí)行、異步執(zhí)行
用GCD創(chuàng)建多個(gè)子線程刚陡,要求在子線程全部完成任務(wù)之后執(zhí)行某操作惩妇,應(yīng)該怎么做?
其實(shí)這個(gè)問題我們只要回答利用GCD并行執(zhí)行多個(gè)線程,等待所有線程結(jié)束之后再執(zhí)行其他任務(wù) 用我們上面說過的隊(duì)列組的方法就OK 然后問怎么判斷這些任務(wù)都執(zhí)行完了,其實(shí)dispatch_group_notify函數(shù)里面的block就是
a.創(chuàng)建隊(duì)列組
b.創(chuàng)建全局隊(duì)列
c.多次使用隊(duì)列組方法執(zhí)行任務(wù)
d.都完成后會(huì)自動(dòng)通知