喜歡就關(guān)注我唄!
1.設(shè)計(jì)模式是什么萝快? 你知道哪些設(shè)計(jì)模式锻霎,并簡(jiǎn)要敘述?
設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn)揪漩,就是用比較成熟的邏輯去處理某一種類型的事情旋恼。
1). MVC模式:Model View Control,把模型 視圖 控制器 層進(jìn)行解耦合編寫奄容。
2). MVVM模式:Model View ViewModel 把模型 視圖 業(yè)務(wù)邏輯 層進(jìn)行解耦和編寫冰更。
3). 單例模式:通過static關(guān)鍵詞,聲明全局變量昂勒。在整個(gè)進(jìn)程運(yùn)行期間只會(huì)被賦值一次冬殃。
4). 觀察者模式:KVO是典型的通知模式,觀察某個(gè)屬性的狀態(tài)叁怪,狀態(tài)發(fā)生變化時(shí)通知觀察者审葬。
5). 委托模式:代理+協(xié)議的組合。實(shí)現(xiàn)1對(duì)1的反向傳值操作奕谭。
6). 工廠模式:通過一個(gè)類方法涣觉,批量的根據(jù)已有模板生產(chǎn)對(duì)象。
2.#import跟 #include 有什么區(qū)別血柳,@class呢
1). #import是Objective-C導(dǎo)入頭文件的關(guān)鍵字官册,#include是C/C++導(dǎo)入頭文件的關(guān)鍵字,使用#import頭文件會(huì)自動(dòng)只導(dǎo)入一次难捌,不會(huì)重復(fù)導(dǎo)入膝宁。
2). @class告訴編譯器某個(gè)類的聲明,當(dāng)執(zhí)行時(shí)根吁,才去查看類的實(shí)現(xiàn)文件员淫,可以解決頭文件的相互包含。
3.Objective-C的類可以多重繼承么击敌?可以實(shí)現(xiàn)多個(gè)接口么介返?Category是什么?重寫一個(gè)類的方式用繼承好還是分類好沃斤?為什么圣蝎?
答:Objective-C的類不可以多重繼承;可以實(shí)現(xiàn)多個(gè)接口(協(xié)議)衡瓶;Category是類別徘公;一般情況用分類好,用Category去重寫類的方法哮针,僅對(duì)本Category有效关面,不會(huì)影響到其他類與原有類的關(guān)系坦袍。
4.@property 的本質(zhì)是什么?ivar缭裆、getter、setter 是如何生成并添加到這個(gè)類中的
@property 的本質(zhì)是什么寿烟?
@property = ivar + getter + setter;
“屬性” (property)有兩大概念:ivar(實(shí)例變量)澈驼、getter+setter(存取方法)
“屬性” (property)作為 Objective-C 的一項(xiàng)特性,主要的作用就在于封裝對(duì)象中的數(shù)據(jù)筛武。 Objective-C 對(duì)象通常會(huì)把其所需要的數(shù)據(jù)保存為各種實(shí)例變量缝其。實(shí)例變量一般通過“存取方法”(access method)來訪問。其中徘六,“獲取方法” (getter)用于讀取變量值内边,而“設(shè)置方法” (setter)用于寫入變量值。
5.什么情況使用 weak 關(guān)鍵字待锈,相比 assign 有什么不同漠其?
1.在 ARC 中,在有可能出現(xiàn)循環(huán)引用的時(shí)候,往往要通過讓其中一端使用 weak 來解決,比如: delegate 代理屬性。
2.自身已經(jīng)對(duì)它進(jìn)行一次強(qiáng)引用,沒有必要再?gòu)?qiáng)引用一次,此時(shí)也會(huì)使用 weak,自定義 IBOutlet 控件屬性一般也使用 weak竿音;當(dāng)然和屎,也可以使用strong。
IBOutlet連出來的視圖屬性為什么可以被設(shè)置成weak?
因?yàn)楦缚丶膕ubViews數(shù)組已經(jīng)對(duì)它有一個(gè)強(qiáng)引用春瞬。
不同點(diǎn):
assign 可以用非 OC 對(duì)象柴信,而 weak 必須用于 OC 對(duì)象。
weak 表明該屬性定義了一種“非擁有關(guān)系”宽气。在屬性所指的對(duì)象銷毀時(shí)随常,屬性值會(huì)自動(dòng)清空(nil)。
6.淺拷貝和深拷貝的區(qū)別萄涯?
答:
淺拷貝:只復(fù)制指向?qū)ο蟮闹羔樞鞣眨粡?fù)制引用對(duì)象本身。
深拷貝:復(fù)制引用對(duì)象本身涝影。內(nèi)存中存在了兩份獨(dú)立對(duì)象本身钞楼,當(dāng)修改A時(shí),A_copy不變袄琳。
NSString *str = @"hello word!";
NSString *strCopy = [str copy] // 指針復(fù)制询件,strCopy與str的地址一樣
NSMutableString *strMCopy = [str mutableCopy] // 內(nèi)容復(fù)制,strMCopy與str的地址不一樣
7.寫一個(gè) setter 方法用于完成 @property (nonatomic, retain) NSString*name唆樊,寫一個(gè) setter 方法用于完成 @property (nonatomic, copy) NSString *name
答:
// retain
- (void)setName:(NSString *)str {
[str retain];
[_name release];
_name = str;
}
// copy
- (void)setName:(NSString *)str {
id t = [str copy];
[_name release];
_name = t;
}
8.@synthesize 和 @dynamic 分別有什么作用宛琅?
@property有兩個(gè)對(duì)應(yīng)的詞,一個(gè)是@synthesize(合成實(shí)例變量)逗旁,一個(gè)是@dynamic嘿辟。
如果@synthesize和@dynamic都沒有寫舆瘪,那么默認(rèn)的就是 @synthesize var = _var;
// 在類的實(shí)現(xiàn)代碼里通過 @synthesize 語法可以來指定實(shí)例變量的名字。(@synthesize var = _newVar;)
1. @synthesize 的語義是如果你沒有手動(dòng)實(shí)現(xiàn)setter方法和getter方法红伦,那么編譯器會(huì)自動(dòng)為你加上這兩個(gè)方法英古。
2. @dynamic 告訴編譯器,屬性的setter與getter方法由用戶自己實(shí)現(xiàn)昙读,不自動(dòng)生成(如召调,@dynamic var)。
9.id 聲明的對(duì)象有什么特性蛮浑?
答:id 聲明的對(duì)象具有運(yùn)行時(shí)的特性唠叛,即可以指向任意類型的Objcetive-C的對(duì)象。
10.Objective-C 中創(chuàng)建線程的方法是什么沮稚?如果在主線程中執(zhí)行代碼艺沼,方法是什么?如果想延時(shí)執(zhí)行代碼蕴掏、方法又是什么障般?
答:線程創(chuàng)建有三種方法:使用NSThread創(chuàng)建、使用GCD的dispatch盛杰、使用子類化的NSOperation,然后將其加入NSOperationQueue;在主線程執(zhí)行代碼剩拢,方法是performSelectorOnMainThread,如果想延時(shí)執(zhí)行代碼可以用performSelector:onThread:withObject:waitUntilDone:
11.我們說的OC是動(dòng)態(tài)運(yùn)行時(shí)語言是什么意思饶唤?
答:主要是將數(shù)據(jù)類型的確定由編譯時(shí)徐伐,推遲到了運(yùn)行時(shí)。簡(jiǎn)單來說, 運(yùn)行時(shí)機(jī)制使我們直到運(yùn)行時(shí)才去決定一個(gè)對(duì)象的類別,以及調(diào)用該類別對(duì)象指定方法募狂。
12.什么是 KVO 和 KVC办素?
1). KVC(Key-Value-Coding):鍵值編碼 是一種通過字符串間接訪問對(duì)象的方式(即給屬性賦值)
舉例說明:
stu.name = @"張三" // 點(diǎn)語法給屬性賦值
[stu setValue:@"張三" forKey:@"name"]; // 通過字符串使用KVC方式給屬性賦值
stu1.nameLabel.text = @"張三";
[stu1 setValue:@"張三" forKey:@"nameLabel.text"]; // 跨層賦值
2). KVO(key-Value-Observing):鍵值觀察機(jī)制 他提供了觀察某一屬性變化的方法,極大的簡(jiǎn)化了代碼祸穷。
KVO只能被KVC觸發(fā)性穿,包括使用setValue:forKey:方法和點(diǎn)語法。
// 通過下方方法為屬性添加KVO觀察
- (void)addObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(nullable void *)context;
// 當(dāng)被觀察的屬性發(fā)送變化時(shí)雷滚,會(huì)自動(dòng)觸發(fā)下方方法
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context{}
KVC 和 KVO 的 keyPath 可以是屬性需曾、實(shí)例變量、成員變量祈远。
13.KVC的底層實(shí)現(xiàn)呆万?
當(dāng)一個(gè)對(duì)象調(diào)用setValue方法時(shí),方法內(nèi)部會(huì)做以下操作:
1). 檢查是否存在相應(yīng)的key的set方法车份,如果存在谋减,就調(diào)用set方法。
2). 如果set方法不存在扫沼,就會(huì)查找與key相同名稱并且?guī)聞澗€的成員變量出爹,如果有庄吼,則直接給成員變量屬性賦值。
3). 如果沒有找到_key严就,就會(huì)查找相同名稱的屬性key总寻,如果有就直接賦值。
4). 如果還沒有找到梢为,則調(diào)用valueForUndefinedKey:和setValue:forUndefinedKey:方法渐行。
這些方法的默認(rèn)實(shí)現(xiàn)都是拋出異常,我們可以根據(jù)需要重寫它們抖誉。
24.談?wù)?UITableView 的優(yōu)化
1). 正確的復(fù)用cell殊轴。
2). 設(shè)計(jì)統(tǒng)一規(guī)格的Cell
3). 提前計(jì)算并緩存好高度(布局)衰倦,因?yàn)閔eightForRowAtIndexPath:是調(diào)用最頻繁的方法袒炉;
4). 異步繪制,遇到復(fù)雜界面樊零,遇到性能瓶頸時(shí)我磁,可能就是突破口;
4). 滑動(dòng)時(shí)按需加載驻襟,這個(gè)在大量圖片展示夺艰,網(wǎng)絡(luò)加載的時(shí)候很管用!
5). 減少子視圖的層級(jí)關(guān)系
6). 盡量使所有的視圖不透明化以及做切圓操作沉衣。
7). 不要?jiǎng)討B(tài)的add 或者 remove 子控件郁副。最好在初始化時(shí)就添加完,然后通過hidden來控制是否顯示豌习。
8). 使用調(diào)試工具分析問題存谎。
14.delegate 和 notification 的區(qū)別
1). 二者都用于傳遞消息,不同之處主要在于一個(gè)是一對(duì)一的肥隆,另一個(gè)是一對(duì)多的既荚。
2). notification通過維護(hù)一個(gè)array,實(shí)現(xiàn)一對(duì)多消息的轉(zhuǎn)發(fā)栋艳。
3). delegate需要兩者之間必須建立聯(lián)系恰聘,不然沒法調(diào)用代理的方法;notification不需要兩者之間有聯(lián)系吸占。
15.您一般是怎么用 Instruments 的?
Time Profiler:性能分析
Zombies:檢查是否訪問了僵尸對(duì)象,但是這個(gè)工具只能從上往下檢查,不智能
Allocations:用來檢查內(nèi)存,寫算法的那批人也用這個(gè)來檢查
Leaks:檢查內(nèi)存,看是否有內(nèi)存泄露
Core Animation:
1)查看幀數(shù) <55就得優(yōu)化 ?優(yōu)化晴叨。
Core Animation工具中有幾個(gè)和離屏渲染相關(guān)的檢查選項(xiàng):
2)Color Offscreen-Rendered Yellow
開啟后會(huì)把那些需要離屏渲染的圖層高亮成黃色,這就意味著黃色圖層可能存在性能問題矾屯。
3)Color Hits Green and Misses Red
如果shouldRasterize被設(shè)置成YES篙螟,對(duì)應(yīng)的渲染結(jié)果會(huì)被緩存,如果圖層是綠色问拘,就表示這些緩存被復(fù)用遍略;如果是紅色就表示緩存會(huì)被重復(fù)創(chuàng)建惧所,這就表示該處存在性能問題了。
16.您開發(fā)常用的工具有哪些绪杏?
1).友盟統(tǒng)計(jì)
2).青花瓷:這個(gè)軟件還是蠻不錯(cuò)的,可以用來過濾網(wǎng)絡(luò)請(qǐng)求,模擬低速網(wǎng)路,還可以修改網(wǎng)絡(luò)請(qǐng)求內(nèi)容這些
3).Reveal:調(diào)試頁面不錯(cuò),還有用來學(xué)習(xí)別人的demo時(shí)候可以拿來看UI層次結(jié)構(gòu),還可以用
17.您是怎么調(diào)試iOS程序的(談?wù)勀膇OS調(diào)試經(jīng)驗(yàn))
斷點(diǎn)調(diào)試下愈,讓程序在執(zhí)行某一行代碼是停止下來,然后來檢查當(dāng)前程序是否正常蕾久。斷點(diǎn)的種類很多势似,可以幫助我們快速定位到問題發(fā)生時(shí)的上下文。
- 普通斷點(diǎn)
- 符號(hào)斷點(diǎn)
- 異常斷點(diǎn)
- watch斷點(diǎn)
- 條件斷點(diǎn)
運(yùn)行時(shí)變量:查看運(yùn)行時(shí)變量值
運(yùn)行時(shí)堆棧:查看函數(shù)的調(diào)用關(guān)系僧著,順序
日志:通過在程序中添加NSLog代碼履因,在控件臺(tái)中輸出顯示日志。
靜態(tài)代碼檢查:通過對(duì)代碼靜態(tài)分析盹愚,找出代碼潛在的錯(cuò)誤栅迄,如內(nèi)存泄漏、空引用皆怕、未使用函數(shù)等毅舆。
動(dòng)態(tài)分析:通過Instruments工具跟蹤分析程序運(yùn)行時(shí)的數(shù)據(jù)
18.有哪些常見的 Crash 場(chǎng)景?
訪問了僵尸對(duì)象
訪問野指針
訪問了不存在的方法
數(shù)組越界
在定時(shí)器下一次回調(diào)前將定時(shí)器釋放
19.如何調(diào)試BAD_ACCESS錯(cuò)誤
1)重寫object的respondsToSelector方法愈腾,現(xiàn)實(shí)出現(xiàn)EXEC_BAD_ACCESS前訪問的最后一個(gè)object
2)通過 Zombie
3)設(shè)置全局?jǐn)帱c(diǎn)快速定位問題代碼所在行
4)Xcode 7 已經(jīng)集成了BAD_ACCESS捕獲功能:Address Sanitizer憋活。 用法如下:在配置中勾選?
Enable Address Sanitizer
20.lldb(gdb)常用的調(diào)試命令?
breakpoint 設(shè)置斷點(diǎn)定位到某一個(gè)函數(shù)
n 斷點(diǎn)指針下一步
po打印對(duì)象
21.如果在Cocoa中發(fā)現(xiàn)一個(gè)Bug虱黄,你會(huì)如何處理悦即?
復(fù)現(xiàn)bug,確認(rèn)bug發(fā)生的軟硬件環(huán)境橱乱,詳細(xì)描述后發(fā)報(bào)告給Apple辜梳。
22.CocoaPods的原理
CocoaPods的原理是將所有的依賴庫都放到另一個(gè)名為Pods的項(xiàng)目中,然后讓主項(xiàng)目依賴Pods項(xiàng)目仅醇,這樣冗美,源碼管理工作都從主項(xiàng)目移到了Pods項(xiàng)目中。Pods項(xiàng)目最終會(huì)編譯成一個(gè)名為libPods.a的文件析二,主項(xiàng)目只需要依賴這個(gè).a文件即可粉洼。
23.請(qǐng)用預(yù)處理指令#define聲明一個(gè)常數(shù),用以表明1年中有多少秒(忽略閏年問題)
#define SECONDS_PER_YEAR (60*60*24*365)_U_LONG
24.volatile表示變量隨時(shí)可以改變
25.請(qǐng)談?wù)刓#include與\#import的區(qū)別叶摄、\#import與@class 的區(qū)別
#include和#import 其效果相同,都是導(dǎo)入類中定義的行為(方法);
#import 不會(huì)引起交叉編譯,確保頭文件只會(huì)被導(dǎo)入一次属韧;
@class 表明只定義了類的名稱,而具體類的行為是未知的,一般用于.h 文件
@class比#import編譯效率更高。此外@class和#import的主要區(qū)別在于解決引用死鎖的問題蛤吓。
26.什么是id類型宵喂,id 聲明的對(duì)象有什么特性?
id 聲明的對(duì)象具有運(yùn)行時(shí)的特性,即可以指向任意類型的objcetive-c的對(duì)象;
27.請(qǐng)談一談關(guān)鍵字self会傲、super的作用
self:當(dāng)前消息的接收者锅棕。
super:向父類發(fā)送消息拙泽。
28.請(qǐng)解釋self = [super init]方法
容錯(cuò)處理,當(dāng)父類初始化失敗,會(huì)返回一個(gè)nil,表示初始化失敗。由于繼承的關(guān)系,子類是需要擁有父類的實(shí)例和行為,因此,我們必須先初始化父類,然后再初始化子類
29.請(qǐng)說明如何使用Instancetype及其重要性
instancetype,編譯器能正確的推斷出返回實(shí)例的實(shí)際類型!
instancetype只能用于返回值!
建議在返回self實(shí)例的方法中,用instancetype,別用id.
30.請(qǐng)問@property中有哪些屬性關(guān)鍵字裸燎?
原子性---atomic/nonatomic? 讀/寫權(quán)限---readwrite(讀寫)顾瞻、readonly(只讀)? 、內(nèi)存管理語義---assign德绿、strong荷荤、weak、unsafe_unretained移稳、copy蕴纳、方法名---getter=和setter=、不常用的:nonnull,null_resettable,nullable
31.ARC下个粱,不顯式指定任何屬性關(guān)鍵字時(shí)古毛,默認(rèn)的關(guān)鍵字都有哪些?
atomic几蜻,readwrite喇潘,assign体斩,strong
32.@protocol 和 category 中如何使用 @property
在 protocol 中使用 property 只會(huì)生成 setter 和 getter 方法聲明,我們使用屬性的目的,是希望遵守我協(xié)議的對(duì)象能實(shí)現(xiàn)該屬性
category 使用 @property 也是只會(huì)生成 setter 和 getter 方法的聲明,如果我們真的需要給 category 增加屬性的實(shí)現(xiàn),需要借助于運(yùn)行時(shí)的兩個(gè)函數(shù):
objc_setAssociatedObject
objc_getAssociatedObject
33.這個(gè)寫法會(huì)出什么問題: @property (copy) NSMutableArray *array;
兩個(gè)問題:
添加,刪除,修改數(shù)組內(nèi)的元素的時(shí)候,程序會(huì)因?yàn)檎也坏綄?duì)應(yīng)的方法而崩潰.因?yàn)?copy 就是復(fù)制一個(gè)不可變 NSArray 的對(duì)象梭稚;
使用了 atomic 屬性會(huì)嚴(yán)重影響性能 ;
34.@synthesize合成實(shí)例變量的規(guī)則是什么絮吵?假如property名為foo弧烤,存在一個(gè)名為_foo的實(shí)例變量,那么還會(huì)自動(dòng)合成新變量么蹬敲?
總結(jié)下 @synthesize 合成實(shí)例變量的規(guī)則暇昂,有以下幾點(diǎn):
如果指定了成員變量的名稱,會(huì)生成一個(gè)指定的名稱的成員變量,
如果這個(gè)成員已經(jīng)存在了就不再生成了.
如果是 @synthesize foo;
還會(huì)生成一個(gè)名稱為foo的成員變量,也就是說:
如果沒有指定成員變量的名稱會(huì)自動(dòng)生成一個(gè)屬性同名的成員變量,
如果是 @synthesize foo = _foo;
就不會(huì)生成成員變量了.
假如 property 名為 foo伴嗡,存在一個(gè)名為 _foo的實(shí)例變量急波,那么還會(huì)自動(dòng)合成新變量么? 不會(huì)瘪校。
34.如何為 Class 定義一個(gè)對(duì)外只讀對(duì)內(nèi)可讀寫的屬性?
在頭文件中將屬性定義為readonly, 在.m文件中將屬性重新定義為readwrite
35.在一個(gè)對(duì)象的方法里面:`self.name = @"object";`和`name =@"object";`有什么不同嗎?
self.name = @"object";會(huì)調(diào)用對(duì)象的setName()方法.
name =@"object";會(huì)直接把@"object"賦值給當(dāng)前對(duì)象的name 屬性澄暮。
block 不能修改局部變量,如果需要修改需要加上block.
block 會(huì)對(duì)對(duì)象強(qiáng)引用阱扬,引起retain-cycle泣懊,需要使用weak
37.使用block有什么好處?請(qǐng)使用`NSTimer`寫出一個(gè)使用block顯示(在`UILabel`上)秒表的代碼
//iOS10 才有效
NSTimer*timer=[NSTimerscheduledTimerWithTimeInterval:1.0repeats:YEScallback:^(){weakSelf.secondsLabel.text=...} ? ?
[[NSRunLoopcurrentRunLoop]addTimer:timerforMode:NSRunLoopCommonModes];
38.談?wù)刡lock使用時(shí)的注意點(diǎn)麻惶?
在block內(nèi)部使用外部指針且會(huì)造成循環(huán)引用情況下,需要用weak修飾外部指針weak typeof(self) weakSelf = self;
在block內(nèi)部如果調(diào)用了延時(shí)函數(shù)還使用弱指針會(huì)取不到該指針,因?yàn)橐呀?jīng)被銷毀了,需要在block內(nèi)部再將弱指針重新強(qiáng)引用一下__strong typeof(self) strongSelf = weakSelf;
如果需要在block內(nèi)部改變外部變量的話,需要在用__block修飾外部變量
39.block和代理的區(qū)別馍刮,哪個(gè)更好?
代理回調(diào)更面向過程窃蹋,block更面向結(jié)果卡啰。FBRetainCycleDetector? ?檢測(cè)循環(huán)引用静稻。
如果你使用一些參數(shù)中可能含有 ivar 的系統(tǒng) api ,如 GCD 匈辱、NSNotificationCenter就要小心一點(diǎn):比如GCD 內(nèi)部如果引用了 self姊扔,而且 GCD 的其他參數(shù)是 iva
_operationsQueue 這個(gè)
__weak__typeof__(self)weakSelf =self;dispatch_group_async(_operationsGroup, _operationsQueue, ^{? ? __typeof__(self)strongSelf= weakSelf;[strongSelfdoSomething];[strongSelfdoSomethingElse];} );
__weak__typeof__(self) weakSelf =self;_observer = [[NSNotificationCenterdefaultCenter] addObserverForName:@"testKey"object:nilqueue:nilusingBlock:^(NSNotification*note) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __typeof__(self) strongSelf = weakSelf;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [strongSelf dismissModalViewControllerAnimated:YES];? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }];
40.類別和類擴(kuò)展的區(qū)別
category和extensions的不同在于后者可以添加屬性。另外后者添加的方法是必須要實(shí)現(xiàn)的梅誓。
extensions可以認(rèn)為是一個(gè)私有的Category恰梢。
41.分類的作用?分類和繼承的區(qū)別梗掰?
分類可以在不獲悉嵌言,不改變?cè)瓉泶a的情況下往里面添加新的方法,只能添加及穗,不能刪除修改摧茴,并且如果分類和原來類中的方法產(chǎn)生名稱沖突,則分類將覆蓋原來的方法埂陆,因?yàn)榉诸惥哂懈叩膬?yōu)先級(jí)苛白。
繼承可以增加,修改或者刪除方法焚虱,并且可以增加屬性购裙;但是分類只能添加方法,不能刪除修改鹃栽,也不能增加屬性躏率。
42.iOS Extension 是什么?能列舉幾個(gè)常用的 Extension 么民鼓?
Extension是Category的一個(gè)特例薇芝,沒有分類名字,可以擴(kuò)展屬性,成員變量和方法丰嘉。
常用的擴(kuò)展是在.m文件中聲明私有屬性和方法夯到,基本上我們天天都在用。
43.addObserver:forKeyPath:options:context:各個(gè)參數(shù)的作用分別是什么饮亏,observer中需要實(shí)現(xiàn)哪個(gè)方法才能獲得KVO回調(diào)耍贾?
// 添加鍵值觀察/*
1 觀察者,負(fù)責(zé)處理監(jiān)聽事件的對(duì)象
2 觀察的屬性
3 觀察的選項(xiàng)
4 上下文
*/[self.personaddObserver:selfforKeyPath:@"name"options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOldcontext:@"Person Name"];
// 所有的 kvo 監(jiān)聽到事件克滴,都會(huì)調(diào)用此方法/*
1. 觀察的屬性
2. 觀察的對(duì)象
3. change 屬性變化字典(新/舊)
4. 上下文逼争,與監(jiān)聽的時(shí)候傳遞的一致
*/- (void)observeValueForKeyPath:(NSString *)keyPathofObject:(id)objectchange:(NSDictionary *)changecontext:(void*)context;
44.如何手動(dòng)觸發(fā)一個(gè)value的KVO
那么“手動(dòng)觸發(fā)”的使用場(chǎng)景是什么?一般我們只在希望能控制“回調(diào)的調(diào)用時(shí)機(jī)”時(shí)才會(huì)這么做劝赔。
具體做法如下:
如果這個(gè)? value 是 表示時(shí)間的 self.now 誓焦,那么代碼如下:最后兩行代碼缺一不可。
@property (nonatomic, strong) NSDate *now;
- (void)viewDidLoad{ ??
?[super viewDidLoad]; ? ?
[self willChangeValueForKey:@"now"];// “手動(dòng)觸發(fā)self.now的KVO”,必寫杂伟。
[self didChangeValueForKey:@"now"];// “手動(dòng)觸發(fā)self.now的KVO”移层,必寫。
}
45.若一個(gè)類有實(shí)例變量NSString *_foo赫粥,調(diào)用setValue:forKey:時(shí)观话,可以以foo還是_foo作為key?
可以越平。kvc機(jī)制频蛔。
46.KVC的keyPath中的集合運(yùn)算符如何使用?
必須用在集合對(duì)象上或普通對(duì)象的集合屬性上
簡(jiǎn)單集合運(yùn)算符有@avg秦叛, @count 晦溪, @max , @min 挣跋,@sum三圆,
格式 @"@sum.age"或 @"集合屬性.@max.age"
http://www.cnblogs.com/panda1024/p/6014399.html
47.KVC和KVO的keyPath一定是屬性么?
KVO支持實(shí)例變量
48.如何關(guān)閉默認(rèn)的KVO的默認(rèn)實(shí)現(xiàn)避咆,并進(jìn)入自定義的KVO實(shí)現(xiàn)舟肉?
http://tech.glowing.com/cn/implement-kvo/
49.apple用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO?
KVO 在實(shí)現(xiàn)中通過isa 混寫(isa-swizzling)把這個(gè)對(duì)象的 isa 指針 ( isa 指針告訴 Runtime 系統(tǒng)這個(gè)對(duì)象的類是什么 ) 指向這個(gè)新創(chuàng)建的子類查库,對(duì)象就神奇的變成了新創(chuàng)建的子類的實(shí)例
50.代理的作用路媚?
代理的目的是改變或傳遞控制鏈。允許一個(gè)類在某些特定時(shí)刻通知到其他類膨报,而不需要獲取到那些類的指針磷籍∈嗜伲可以減少框架復(fù)雜度现柠。
另外一點(diǎn),代理可以理解為java中的回調(diào)監(jiān)聽機(jī)制的一種類似弛矛。
51.OC有多繼承嗎够吩?沒有的話用什么代替糙置?
OC中沒有多繼承嗽冒,可以用委托代理Protocol來實(shí)現(xiàn)
52.什么是 Protocol星虹,Delegate 一般是怎么用的溅呢?
Protocol是協(xié)議锻狗,只有.h文件康二,甚至可以不獨(dú)立文件
使用時(shí) 遵守協(xié)議楣导,在本類中實(shí)現(xiàn)方法就可以
協(xié)議有required和optional的蝌衔,required是必須實(shí)現(xiàn)的協(xié)議方法闰歪。
協(xié)議聲明了可以被任何類實(shí)現(xiàn)的方法
協(xié)議不是類嚎研,它是定義了一個(gè)其他對(duì)象可以實(shí)現(xiàn)的接口
如果在某個(gè)類中實(shí)現(xiàn)了協(xié)議中的某個(gè)方法,也就是這個(gè)類實(shí)現(xiàn)了那個(gè)協(xié)議库倘。
Delegate:它本身是一個(gè)設(shè)計(jì)模式临扮,它的意思是委托別人去做某事论矾。
53.為什么 NotificationCenter 要 removeObserver? 如何實(shí)現(xiàn)自動(dòng) remove?
如果不移除的話,萬一注冊(cè)通知的類被銷毀以后又發(fā)了通知,程序會(huì)崩潰.因?yàn)橄蛞爸羔槹l(fā)送了消息
實(shí)現(xiàn)自動(dòng)remove:通過自釋放機(jī)制,通過動(dòng)態(tài)屬性將remove轉(zhuǎn)移給第三者,解除耦合,達(dá)到自動(dòng)實(shí)現(xiàn)remove。
54.我們說的oc是動(dòng)態(tài)運(yùn)行時(shí)語言是什么意思?
OC的動(dòng)態(tài)運(yùn)行時(shí)杆勇,是指OC具有動(dòng)態(tài)類型和動(dòng)態(tài)綁定的特性贪壳。動(dòng)態(tài)類型能使程序直到執(zhí)行時(shí)才確定對(duì)象的所屬類, 其具體引用的對(duì)象在運(yùn)行時(shí)才能確定蚜退。 動(dòng)態(tài)綁定能使程序直到運(yùn)行時(shí)才確定調(diào)用對(duì)象的實(shí)際方法闰靴。
多態(tài)。 主要是將數(shù)據(jù)類型的確定由編譯時(shí)钻注,推遲到了運(yùn)行時(shí)传黄。
這個(gè)問題其實(shí)淺涉及到兩個(gè)概念,運(yùn)行時(shí)和多態(tài)队寇。
簡(jiǎn)單來說膘掰,運(yùn)行時(shí)機(jī)制使我們直到運(yùn)行時(shí)才去決定一個(gè)對(duì)象的類別,以及調(diào)用該類別對(duì)象指定方法佳遣。
多態(tài):不同對(duì)象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)识埋。意思就是假設(shè)生物類(life)都用有一個(gè)相同的方法-eat;
那人類屬于生物,豬也屬于生物零渐,都繼承了life后窒舟,實(shí)現(xiàn)各自的eat,但是調(diào)用是我們只需調(diào)用各自的eat方法诵盼。
也就是不同的對(duì)象以自己的方式響應(yīng)了相同的消息(響應(yīng)了eat這個(gè)選擇器)惠豺。
55.objc中向一個(gè)nil對(duì)象發(fā)送消息將會(huì)發(fā)生什么?
objc在向一個(gè)對(duì)象發(fā)送消息時(shí)风宁,runtime庫會(huì)根據(jù)對(duì)象的isa指針找到該對(duì)象實(shí)際所屬的類洁墙,然后在該類中的方法列表以及其父類方法列表中尋找方法運(yùn)行,然后在發(fā)送消息的時(shí)候戒财,objc_msgSend方法不會(huì)返回值热监,所謂的返回內(nèi)容都是具體調(diào)用時(shí)執(zhí)行的。那么饮寞,回到本題孝扛,如果向一個(gè)nil對(duì)象發(fā)送消息,首先在尋找對(duì)象的isa指針時(shí)就是0地址返回了幽崩,所以不會(huì)出現(xiàn)任何錯(cuò)誤苦始。
56.objc中向一個(gè)對(duì)象發(fā)送消息[obj foo]和objc_msgSend()函數(shù)之間有什么關(guān)系?
[obj foo];在objc動(dòng)態(tài)編譯時(shí)慌申,會(huì)被轉(zhuǎn)意為:objc_msgSend(obj,@selector(foo));
57.為什么其他語言里叫函數(shù)調(diào)用陌选,Object-C里則叫給我對(duì)象發(fā)消息
在OC中,方法調(diào)用是向類發(fā)送消息,如[bady cry]在運(yùn)行時(shí)會(huì)轉(zhuǎn)換成objc_msgSend(bady,cry),向?qū)ο蟀l(fā)送消息時(shí)根據(jù)isa指針找到類,在根據(jù)類的調(diào)度表查找方法柠贤,沒找到方法則在父類中查找直至基類香浩,如果始終沒有找到返回nil。
Objective-C 的 Runtime 鑄就了它動(dòng)態(tài)語言的特性臼勉。Objc Runtime使得C具有了面向?qū)ο竽芰α诳裕诔绦蜻\(yùn)行時(shí)創(chuàng)建,檢查宴霸,修改類囱晴、對(duì)象和它們的方法∑靶唬可以使用runtime的一系列方法實(shí)現(xiàn)畸写。
58.isMemberOfClass 和 isKindOfClass 聯(lián)系與區(qū)別
聯(lián)系:兩者都能檢測(cè)一個(gè)對(duì)象是否是某個(gè)類的成員
區(qū)別:isKindOfClass 不僅用來確定一個(gè)對(duì)象是否是一個(gè)類的成員,也可以用來確定一個(gè)對(duì)象是否派生自該類的類的成員 ,而isMemberOfClass 只能做到第一點(diǎn)。
舉例:如 ClassA派 生 自NSObject 類 , ClassA *a = [ClassA alloc] init];,[a isKindOfClass:[NSObject class]] 可以檢查出 a 是否是 NSObject派生類 的成員,但 isMemberOfClass 做不到氓扛。
59.什么時(shí)候會(huì)報(bào)unrecognized selector的異常枯芬?
簡(jiǎn)單來說:
當(dāng)調(diào)用該對(duì)象上某個(gè)方法,而該對(duì)象上沒有實(shí)現(xiàn)這個(gè)方法的時(shí)候,
可以通過“消息轉(zhuǎn)發(fā)”進(jìn)行解決采郎。
簡(jiǎn)單的流程如下千所,在上一題中也提到過:
objc是動(dòng)態(tài)語言,每個(gè)方法在運(yùn)行時(shí)會(huì)被動(dòng)態(tài)轉(zhuǎn)為消息發(fā)送蒜埋,即:objc_msgSend(receiver, selector)淫痰。
objc在向一個(gè)對(duì)象發(fā)送消息時(shí),runtime庫會(huì)根據(jù)對(duì)象的isa指針找到該對(duì)象實(shí)際所屬的類整份,然后在該類中的方法列表以及其父類方法列表中尋找方法運(yùn)行待错,如果,在最頂層的父類中依然找不到相應(yīng)的方法時(shí)烈评,程序在運(yùn)行時(shí)會(huì)掛掉并拋出異常unrecognized selector sent to XXX 火俄。但是在這之前,objc的運(yùn)行時(shí)會(huì)給出三次拯救程序崩潰的機(jī)會(huì):
Method resolution
objc運(yùn)行時(shí)會(huì)調(diào)用+resolveInstanceMethod:或者 +resolveClassMethod:础倍,讓你有機(jī)會(huì)提供一個(gè)函數(shù)實(shí)現(xiàn)烛占。如果你添加了函數(shù),那運(yùn)行時(shí)系統(tǒng)就會(huì)重新啟動(dòng)一次消息發(fā)送的過程沟启,否則 ,運(yùn)行時(shí)就會(huì)移到下一步犹菇,消息轉(zhuǎn)發(fā)(Message Forwarding)德迹。
Fast forwarding
如果目標(biāo)對(duì)象實(shí)現(xiàn)了-forwardingTargetForSelector:,Runtime 這時(shí)就會(huì)調(diào)用這個(gè)方法揭芍,給你把這個(gè)消息轉(zhuǎn)發(fā)給其他對(duì)象的機(jī)會(huì)胳搞。
只要這個(gè)方法返回的不是nil和self,整個(gè)消息發(fā)送的過程就會(huì)被重啟,當(dāng)然發(fā)送的對(duì)象會(huì)變成你返回的那個(gè)對(duì)象肌毅。否則筷转,就會(huì)繼續(xù)Normal Fowarding。
這里叫Fast悬而,只是為了區(qū)別下一步的轉(zhuǎn)發(fā)機(jī)制呜舒。因?yàn)檫@一步不會(huì)創(chuàng)建任何新的對(duì)象,但下一步轉(zhuǎn)發(fā)會(huì)創(chuàng)建一個(gè)NSInvocation對(duì)象笨奠,所以相對(duì)更快點(diǎn)袭蝗。
Normal forwarding
這一步是Runtime最后一次給你挽救的機(jī)會(huì)。首先它會(huì)發(fā)送-methodSignatureForSelector:消息獲得函數(shù)的參數(shù)和返回值類型般婆。如果-methodSignatureForSelector:返回nil到腥,Runtime則會(huì)發(fā)出-doesNotRecognizeSelector:消息,程序這時(shí)也就掛掉了蔚袍。如果返回了一個(gè)函數(shù)簽名乡范,Runtime就會(huì)創(chuàng)建一個(gè)NSInvocation對(duì)象并發(fā)送-forwardInvocation:消息給目標(biāo)對(duì)象。
60.一個(gè)objc對(duì)象的isa的指針指向什么啤咽?有什么作用篓足?
指向他的類對(duì)象,從而可以找到對(duì)象上的方法
61._objc_msgForward函數(shù)是做什么的,直接調(diào)用它將會(huì)發(fā)生什么闰蚕?
_objc_msgForward是 IMP 類型栈拖,用于消息轉(zhuǎn)發(fā)的:當(dāng)向一個(gè)對(duì)象發(fā)送一條消息,但它并沒有實(shí)現(xiàn)的時(shí)候没陡,_objc_msgForward會(huì)嘗試做消息轉(zhuǎn)發(fā)涩哟。
直接調(diào)用_objc_msgForward是非常危險(xiǎn)的事,如果用不好會(huì)直接導(dǎo)致程序Crash盼玄,但是如果用得好贴彼,能做很多非常酷的事埃儿。
一旦調(diào)用_objc_msgForward器仗,將跳過查找 IMP 的過程,直接觸發(fā)“消息轉(zhuǎn)發(fā)”童番,如果調(diào)用了_objc_msgForward精钮,即使這個(gè)對(duì)象確實(shí)已經(jīng)實(shí)現(xiàn)了這個(gè)方法,你也會(huì)告訴objc_msgSend:“我沒有在這個(gè)對(duì)象里找到這個(gè)方法的實(shí)現(xiàn)”
62.能否向編譯后得到的類中增加實(shí)例變量剃斧?能否向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量轨香?為什么?
不能向編譯后得到的類中增加實(shí)例變量幼东;
能向運(yùn)行時(shí)創(chuàng)建的類中添加實(shí)例變量臂容;
原因如下:
因?yàn)榫幾g后的類已經(jīng)注冊(cè)在 runtime 中科雳,類結(jié)構(gòu)體中的 objc_ivar_list 實(shí)例變量的鏈表 和 instance_size 實(shí)例變量的內(nèi)存大小已經(jīng)確定,同時(shí)runtime 會(huì)調(diào)用 class_setIvarLayout 或 class_setWeakIvarLayout 來處理 strong weak 引用脓杉。所以不能向存在的類中添加實(shí)例變量糟秘;
運(yùn)行時(shí)創(chuàng)建的類是可以添加實(shí)例變量,調(diào)用 class_addIvar 函數(shù)球散。但是得在調(diào)用 objc_allocateClassPair 之后尿赚,objc_registerClassPair 之前,原因同上沛婴。
63.Objective-C 中吼畏,meta-class 指的是什么?
meta-class 是 Class 對(duì)象的類, 為這個(gè)Class類存儲(chǔ)類方法, 當(dāng)一個(gè)類發(fā)送消息時(shí),就去那個(gè)類對(duì)應(yīng)的meta-class中查找那個(gè)消息嘁灯。
每個(gè)Class都有不同的meta-class, 所有的meta-class都使用基類的meta-class(假如類繼承NSObject,那么他所對(duì)應(yīng)的meta-class也是NSObject) 作為他們的類
63.Toll-Free Bridging 是什么泻蚊?什么情況下會(huì)使用?
Toll-Free Bridging用于在Foundation對(duì)象與Core Foundation對(duì)象之間交換數(shù)據(jù),俗稱橋接
在ARC環(huán)境下,Foundation對(duì)象轉(zhuǎn)成 Core Foundation對(duì)象
使用__bridge橋接以后ARC會(huì)自動(dòng)管理2個(gè)對(duì)象
使用__bridge_retained橋接需要手動(dòng)釋放Core Foundation對(duì)象
在ARC環(huán)境下, Core Foundation對(duì)象轉(zhuǎn)成 Foundation對(duì)象
使用__bridge橋接,如果Core Foundation對(duì)象被釋放,Foundation對(duì)象也同時(shí)不能使用了,需要手動(dòng)管理Core Foundation對(duì)象
使用__bridge_transfer橋接,系統(tǒng)會(huì)自動(dòng)管理2個(gè)對(duì)象
63.iOS 是如何管理內(nèi)存的
Objective-C中的對(duì)象都是基于引用計(jì)數(shù)來管理生命周期的丑婿。簡(jiǎn)單來說就是性雄,我們?cè)谛枰钟幸粋€(gè)對(duì)象時(shí),調(diào)用retain讓它的引用計(jì)數(shù)+1羹奉。不需要這個(gè)對(duì)象的時(shí)候秒旋,調(diào)用release讓它的引用計(jì)數(shù)-1。當(dāng)一個(gè)對(duì)象引用計(jì)數(shù)為0的時(shí)候诀拭,這個(gè)對(duì)象就會(huì)被自動(dòng)銷毀
64.ARC通過什么方式幫助開發(fā)者管理內(nèi)存迁筛?
ARC相對(duì)于MRC,不是在編譯時(shí)添加retain/release/autorelease這么簡(jiǎn)單耕挨。應(yīng)該是編譯期和運(yùn)行期兩部分共同幫助開發(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ù)雜,但也不能被忽略奏窑。
65.一個(gè)objc對(duì)象如何進(jìn)行內(nèi)存布局导披?(考慮有父類的情況)
所有父類的成員變量和自己的成員變量都會(huì)存放在該對(duì)象所對(duì)應(yīng)的存儲(chǔ)空間中.
每一個(gè)對(duì)象內(nèi)部都有一個(gè)isa指針,指向他的類對(duì)象,類對(duì)象中存放著本對(duì)象的
對(duì)象方法列表(對(duì)象能夠接收的消息列表,保存在它所對(duì)應(yīng)的類對(duì)象中)
成員變量的列表,
屬性列表,
它內(nèi)部也有一個(gè)isa指針指向元對(duì)象(meta class),元對(duì)象內(nèi)部存放的是類方法列表,類對(duì)象內(nèi)部還有一個(gè)superclass的指針,指向他的父類對(duì)象良哲。
每個(gè) Objective-C 對(duì)象都有相同的結(jié)構(gòu)盛卡,如下圖所示:
翻譯過來就是
ISA指針
根類的實(shí)例變量
倒數(shù)第二層父類的實(shí)例變量
...
父類的實(shí)例變量
類的實(shí)例變量
根對(duì)象就是NSobject,它的superclass指針指向nil
類對(duì)象既然稱為對(duì)象筑凫,那它也是一個(gè)實(shí)例滑沧。類對(duì)象中也有一個(gè)isa指針指向它的元類(meta class),即類對(duì)象是元類的實(shí)例巍实。元類內(nèi)部存放的是類方法列表滓技,根元類的isa指針指向自己,superclass指針指向NSObject類
66.不手動(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í)釋放纬朝。
如果在一個(gè)vc的viewDidLoad中創(chuàng)建一個(gè) Autorelease對(duì)象,那么該對(duì)象會(huì)在 viewDidAppear 方法執(zhí)行前就被銷毀了骄呼。
67.蘋果是如何實(shí)現(xiàn)autoreleasepool的共苛?
autoreleasepool 以一個(gè)棧的形式實(shí)現(xiàn),主要通過下列三個(gè)函數(shù)完成.
objc_autoreleasepoolPush
objc_autoreleasepoolPop
objc_aurorelease
看函數(shù)名就可以知道,對(duì) autorelease 分別執(zhí)行 push蜓萄,和 pop 操作隅茎。銷毀對(duì)象時(shí)執(zhí)行release操作。
68.請(qǐng)談?wù)剝?nèi)存的使用和優(yōu)化的注意事項(xiàng)
重用問題:如UITableViewCells嫉沽、UICollectionViewCells辟犀、UITableViewHeaderFooterViews設(shè)置正確的reuseIdentifier,充分重用绸硕;
盡量把views設(shè)置為不透明:當(dāng)opque為NO的時(shí)候堂竟,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果,可提高性能臣咖;
不要使用太復(fù)雜的XIB/Storyboard:載入時(shí)就會(huì)將XIB/storyboard需要的所有資源跃捣,包括圖片全部載入內(nèi)存,即使未來很久才會(huì)使用夺蛇。那些相比純代碼寫的延遲加載疚漆,性能及內(nèi)存就差了很多;
選擇正確的數(shù)據(jù)結(jié)構(gòu):學(xué)會(huì)選擇對(duì)業(yè)務(wù)場(chǎng)景最合適的數(shù)組結(jié)構(gòu)是寫出高效代碼的基礎(chǔ)刁赦。比如娶聘,數(shù)組: 有序的一組值。使用索引來查詢很快甚脉,使用值查詢很慢丸升,插入/刪除很慢。字典: 存儲(chǔ)鍵值對(duì)牺氨,用鍵來查找比較快狡耻。集合: 無序的一組值墩剖,用值來查找很快,插入/刪除很快夷狰。gzip/zip壓縮:當(dāng)從服務(wù)端下載相關(guān)附件時(shí)岭皂,可以通過gzip/zip壓縮后再下載,使得內(nèi)存更小沼头,下載速度也更快爷绘。
延遲加載:對(duì)于不應(yīng)該使用的數(shù)據(jù),使用延遲加載方式进倍。對(duì)于不需要馬上顯示的視圖土至,使用延遲加載方式。比如猾昆,網(wǎng)絡(luò)請(qǐng)求失敗時(shí)顯示的提示界面陶因,可能一直都不會(huì)使用到,因此應(yīng)該使用延遲加載毡庆。
數(shù)據(jù)緩存:對(duì)于cell的行高要緩存起來坑赡,使得reload數(shù)據(jù)時(shí),效率也極高么抗。而對(duì)于那些網(wǎng)絡(luò)數(shù)據(jù)毅否,不需要每次都請(qǐng)求的,應(yīng)該緩存起來蝇刀,可以寫入數(shù)據(jù)庫螟加,也可以通過plist文件存儲(chǔ)。
處理內(nèi)存警告:一般在基類統(tǒng)一處理內(nèi)存警告吞琐,將相關(guān)不用資源立即釋放掉重用大開銷對(duì)象:一些objects的初始化很慢捆探,比如NSDateFormatter
和NSCalendar,但又不可避免地需要使用它們站粟。通常是作為屬性存儲(chǔ)起來黍图,防止反復(fù)創(chuàng)建。
避免反復(fù)處理數(shù)據(jù):許多應(yīng)用需要從服務(wù)器加載功能所需的常為JSON或者XML格式的數(shù)據(jù)奴烙。在服務(wù)器端和客戶端使用相同的數(shù)據(jù)結(jié)構(gòu)很重要;
使用Autorelease Pool:在某些循環(huán)創(chuàng)建臨時(shí)變量處理數(shù)據(jù)時(shí)助被,自動(dòng)釋放池以保證能及時(shí)釋放內(nèi)存;
正確選擇圖片加載方式:詳情閱讀UIImage加載方式
69.dispatch_barrier_async的作用是什么?
在并行隊(duì)列中切诀,為了保持某些任務(wù)的順序揩环,需要等待一些任務(wù)完成后才能繼續(xù)進(jìn)行,使用 barrier 來等待之前任務(wù)完成幅虑,避免數(shù)據(jù)競(jìng)爭(zhēng)等問題丰滑。
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í)行炫刷。
70.蘋果為什么要廢棄dispatch_get_current_queue?
dispatch_get_current_queue容易造成死鎖
71.如何用GCD同步若干個(gè)異步調(diào)用貌亭?(如根據(jù)若干個(gè)url異步加載多張圖片柬唯,然后在都下載完成后合成一張整圖)
使用Dispatch Group追加block到Global Group Queue,這些block如果全部執(zhí)行完畢认臊,就會(huì)執(zhí)行Main Dispatch Queue中的結(jié)束處理的block
dispatch_queue_tqueue= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_tgroup= dispatch_group_create();
dispatch_group_async(group,queue, ^{/*加載圖片1 */});
dispatch_group_async(group,queue, ^{/*加載圖片2 */});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{// 合并圖片});
73.什么是 Runloop圃庭?RunLoop都有些模式?為什么 UIScrollView 的滾動(dòng)會(huì)導(dǎo)致 NSTimer 失效失晴?
model 主要是用來指定事件在運(yùn)行循環(huán)中的優(yōu)先級(jí)的剧腻,分為:
NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默認(rèn),空閑狀態(tài)
UITrackingRunLoopMode:ScrollView滑動(dòng)時(shí)
UIInitializationRunLoopMode:?jiǎn)?dòng)時(shí)
NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
蘋果公開提供的 Mode 有兩個(gè):
NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
NSRunLoopCommonModes(kCFRunLoopCommonModes)
定時(shí)器里面有個(gè)runoop mode,一般定時(shí)器是運(yùn)行在defaultmode上涂屁。但是如果滑動(dòng)了這個(gè)頁面,主線程runloop會(huì)轉(zhuǎn)到UITrackingRunLoopMode中,這時(shí)候就不能處理定時(shí)器了,造成定時(shí)器失效,原因就是runroop mode選錯(cuò)了,解決辦法有2個(gè)
一個(gè)是更改mode為NSRunLoopCommonModes(無論runloop運(yùn)行在哪個(gè)mode,都能運(yùn)行),
還有種辦法是切換到主線程來更新UI界面的刷新
74.UITableViewCell上有個(gè)UILabel书在,顯示NSTimer實(shí)現(xiàn)的秒表時(shí)間,手指滾動(dòng)cell過程中拆又,label是否刷新儒旬,為什么?
這是否刷新取決于timer加入到Run Loop中的Mode是什么帖族。
75.猜想runloop內(nèi)部是如何實(shí)現(xiàn)的栈源?
functionloop()
{ ? initialize();
do{
var message = get_next_message();? ? ??
? process_message(message);? ?
?}while(message != quit);}
int ? main(intargc,char* argv[]){
//程序一直運(yùn)行狀態(tài)
while(AppIsRunning) {
//睡眠狀態(tài),等待喚醒事件
id whoWakesMe = SleepForWakingUp();
//得到喚醒事件
idevent= GetEvent(whoWakesMe);
//開始處理事件
HandleEvent(event);??
? }return0;}
76.runloop和線程有什么關(guān)系竖般?
主線程的run loop默認(rèn)是啟動(dòng)的甚垦。
對(duì)其它線程來說,run loop默認(rèn)是沒有啟動(dòng)的涣雕,如果你需要更多的線程交互則可以手動(dòng)配置和啟動(dòng)艰亮,如果線程只是去執(zhí)行一個(gè)長(zhǎng)時(shí)間的已確定的任務(wù)則不需要。
在任何一個(gè) Cocoa 程序的線程中挣郭,都可以通過以下代碼來獲取到當(dāng)前線程的 run loop 迄埃。
run loop和線程是緊密相連的,可以這樣說run loop是為了線程而生兑障,沒有線程侄非,它就沒有存在的必要。Run loops是線程的基礎(chǔ)架構(gòu)部分
77.iOS 7的多任務(wù)添加了哪兩個(gè)新的 API? 各自的使用場(chǎng)景是什么旺垒?
后臺(tái)獲炔士狻(Background Fetch):后臺(tái)獲取使用場(chǎng)景是用戶打開應(yīng)用之前就使app有機(jī)會(huì)執(zhí)行代碼來獲取數(shù)據(jù),刷新UI先蒋。這樣在用戶打開應(yīng)用的時(shí)候骇钦,最新的內(nèi)容將已然呈現(xiàn)在用戶眼前,而省去了所有的加載過程竞漾。
推送喚醒(Remote Notifications):使用場(chǎng)景是使設(shè)備在接收到遠(yuǎn)端推送后讓系統(tǒng)喚醒設(shè)備和我們的后臺(tái)應(yīng)用眯搭,并先執(zhí)行一段代碼來準(zhǔn)備數(shù)據(jù)和UI窥翩,然后再提示用戶有推送。這時(shí)用戶如果解鎖設(shè)備進(jìn)入應(yīng)用后將不會(huì)再有任何加載過程鳞仙,新的內(nèi)容將直接得到呈現(xiàn)寇蚊。
78.請(qǐng)解釋一下Handoff是什么,并簡(jiǎn)述它是如何實(shí)現(xiàn)iOS棍好、Mac/網(wǎng)頁應(yīng)用互通的仗岸。
Handoff 是在 OS X 和 iOS 跨設(shè)備連續(xù)性的拓展的用戶體驗(yàn)的功能。Handoff 使用戶可以在一臺(tái)設(shè)備中開始一個(gè)活動(dòng)借笙,然后切換到其他設(shè)備并在該設(shè)備恢復(fù)相同的活動(dòng)扒怖。例如,某個(gè)用戶從 Safari 移到登陸了相同的 Apple ID 賬戶的 iOS 設(shè)備瀏覽一篇很長(zhǎng)的文章业稼,相同的頁面會(huì)在 iOS 的 Safari 打開盗痒,并且滾動(dòng)條位置和啟始設(shè)備相同,Handoff 使這個(gè)體驗(yàn)盡可能平穩(wěn)順暢低散。
79.內(nèi)存管理主要分兩種模式俯邓,MRC 和ARC
1、MRC MRC是手動(dòng)管理內(nèi)存熔号,xcode4.1以及一下版本沒有ARC
引用計(jì)數(shù)概念 retain +1 release -1
內(nèi)存釋放池Release Pool:把需要釋放的內(nèi)存統(tǒng)一放在一個(gè)池子中稽鞭,當(dāng)池子被抽干后(drain),池子中所有的內(nèi)存空間也被自動(dòng)釋放掉跨嘉。內(nèi)存池的釋放操作分為自動(dòng)和手動(dòng)川慌。自動(dòng)釋放受runloop機(jī)制影響。
2祠乃、ARC ACR是自動(dòng)管理內(nèi)存梦重,自動(dòng)引用計(jì)數(shù) 重點(diǎn):循環(huán)引用,用weak 修飾來釋放(block亮瓷,delegate會(huì)出現(xiàn)這種情況)