# iOS基礎(chǔ) # iOS面試題二

如果你不知道你接下來(lái)需要補(bǔ)充學(xué)習(xí)哪一部分知識(shí),做點(diǎn)面試題吧划乖。

接上文

61贬养、NStimer準(zhǔn)嗎?談?wù)勀愕目捶ㄇ兮郑咳绻粶?zhǔn)該怎樣實(shí)現(xiàn)一個(gè)精確的NSTimer?

1.不準(zhǔn)

2.不準(zhǔn)的原因如下:

1误算、NSTimer加在main runloop中,模式是NSDefaultRunLoopMode迷殿,main負(fù)責(zé)所有主線程事件儿礼,例如UI界面的操作,復(fù)雜的運(yùn)算庆寺,這樣在同一個(gè)runloop中timer就會(huì)產(chǎn)生阻塞蚊夫。

2、模式的改變止邮。主線程的 RunLoop 里有兩個(gè)預(yù)置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode这橙。

當(dāng)你創(chuàng)建一個(gè) Timer 并加到 DefaultMode 時(shí)奏窑,Timer 會(huì)得到重復(fù)回調(diào),但此時(shí)滑動(dòng)一個(gè)ScrollView時(shí)屈扎,RunLoop 會(huì)將 mode 切換為 TrackingRunLoopMode埃唯,這時(shí) Timer 就不會(huì)被回調(diào),并且也不會(huì)影響到滑動(dòng)操作鹰晨。所以就會(huì)影響到NSTimer不準(zhǔn)的情況墨叛。

PS:DefaultMode 是 App 平時(shí)所處的狀態(tài),rackingRunLoopMode 是追蹤 ScrollView 滑動(dòng)時(shí)的狀態(tài)模蜡。

方法一:

1漠趁、在主線程中進(jìn)行NSTimer操作,但是將NSTimer實(shí)例加到main runloop的特定mode(模式)中忍疾。避免被復(fù)雜運(yùn)算操作或者UI界面刷新所干擾闯传。

self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(showTime) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

2、在子線程中進(jìn)行NSTimer的操作卤妒,再在主線程中修改UI界面顯示操作結(jié)果甥绿;

- (void)timerMethod2 {
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];
[thread start];
}
- (void)newThread
{
@autoreleasepool
{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(showTime) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run];
}
}
總結(jié):

一開(kāi)始的時(shí)候系統(tǒng)就為我們將主線程的main runloop隱式的啟動(dòng)了。

在創(chuàng)建線程的時(shí)候则披,可以主動(dòng)獲取當(dāng)前線程的runloop共缕。每個(gè)子線程對(duì)應(yīng)一個(gè)runloop

方法二:

使用示例

使用mach內(nèi)核級(jí)的函數(shù)可以使用mach_absolute_time()獲取到CPU的tickcount的計(jì)數(shù)值,可以通過(guò)”mach_timebase_info”函數(shù)獲取到納秒級(jí)的精確度 士复。然后使用mach_wait_until(uint64_t deadline)函數(shù)图谷,直到指定的時(shí)間之后,就可以執(zhí)行指定任務(wù)了阱洪。

關(guān)于數(shù)據(jù)結(jié)構(gòu)mach_timebase_info的定義如下:

struct mach_timebase_info {uint32_t numer;uint32_t denom;};
#include
#include
static const uint64_t NANOS_PER_USEC = 1000ULL;
static const uint64_t NANOS_PER_MILLISEC = 1000ULL * NANOS_PER_USEC;
static const uint64_t NANOS_PER_SEC = 1000ULL * NANOS_PER_MILLISEC;
static mach_timebase_info_data_t timebase_info;
static uint64_t nanos_to_abs(uint64_t nanos) {
return nanos * timebase_info.denom / timebase_info.numer;
}
void example_mach_wait_until(int seconds)
{
mach_timebase_info(&timebase_info);
uint64_t time_to_wait = nanos_to_abs(seconds * NANOS_PER_SEC);
uint64_t now = mach_absolute_time();
mach_wait_until(now + time_to_wait);
}
方法三:直接使用GCD替代便贵!
 
 cgd timer
 

self.gcdTime = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
// 開(kāi)始時(shí)間支持納秒級(jí)別
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)2 * NSEC_PER_SEC);
// 2秒執(zhí)行一次
uint64_t dur = (uint64_t)(2.0 * NSEC_PER_SEC);
// 最后一個(gè)參數(shù)是允許的誤差,即使設(shè)為零冗荸,系統(tǒng)也會(huì)有默認(rèn)的誤差
dispatch_source_set_timer(self.gcdTime, start, dur, 0);
// 設(shè)置回調(diào)
dispatch_source_set_event_handler(self.gcdTime, ^{
    NSLog(@"---%@---%@",[NSThread currentThread],self);
});


取消定時(shí)器:dispatch_cancel(self.gcdTimer);

62嫉沽、你知道哪些設(shè)計(jì)模式,并簡(jiǎn)要敘述俏竞?

1). MVC模式:Model View Control绸硕,把模型 視圖 控制器 層進(jìn)行解耦合編寫(xiě)。
2). MVVM模式:Model View ViewModel 把模型 視圖 業(yè)務(wù)邏輯 層進(jìn)行解耦和編寫(xiě)魂毁。
3). 單例模式:通過(guò)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). 工廠模式:通過(guò)一個(gè)類(lèi)方法,批量的根據(jù)已有模板生產(chǎn)對(duì)象兜蠕。

63扰肌、import 跟 #include 有什么區(qū)別,@class呢熊杨,#import<> 跟 #import”” 有什么區(qū)別曙旭?

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è)類(lèi)的聲明川陆,當(dāng)執(zhí)行時(shí)剂习,才去查看類(lèi)的實(shí)現(xiàn)文件,可以解決頭文件的相互包含较沪。
3. #import<> 用來(lái)包含系統(tǒng)的頭文件进倍,#import””用來(lái)包含用戶頭文件。

64购对、tableView的重用機(jī)制能簡(jiǎn)單說(shuō)一下么?

cell池
visibleCells 當(dāng)前顯示的cells

reusableTableCells 保存重用的cells

dequeueReusableCellWithIdentifier 獲取重用cell

超出屏幕的時(shí)候 更新 reusableTableCells
reload的時(shí)候  更新 reusableTableCells

reusableTableCells為空的話  reloadRowsAtIndex 也會(huì)更新

65陶因、寫(xiě)一個(gè)線程安全的單例模式 - 保證線程安全的方式

加鎖和GCD柵欄骡苞,隊(duì)列組相關(guān)知識(shí)

66、在手勢(shì)對(duì)象基礎(chǔ)類(lèi)UIGestureRecognizer的常用子類(lèi)手勢(shì)類(lèi)型中哪兩個(gè)手勢(shì)發(fā)生后楷扬,響應(yīng)只會(huì)執(zhí)行一次解幽?

UITapGestureRecognizer,UISwipeGestureRecognizer是一次性手勢(shì),手勢(shì)發(fā)生后,響應(yīng)只會(huì)執(zhí)行一次。

67烘苹、自定義庫(kù)要注意些什么

抽象和封裝躲株,方便使用。

首先是對(duì)問(wèn)題有充分的了解镣衡,比如構(gòu)建一個(gè)文件解壓壓縮框架霜定,從使用者的角度出發(fā),只需關(guān)注發(fā)送給框架一個(gè)解壓請(qǐng)求廊鸥,框架完成復(fù)雜文件的解壓操作望浩,

并且在適當(dāng)?shù)臅r(shí)候通知給使用者,如解壓完成惰说、解壓出錯(cuò)等磨德。

在框架內(nèi)部去構(gòu)建對(duì)象的關(guān)系,通過(guò)抽象讓其更為健壯、便于更改典挑。其次是API的說(shuō)明文檔酥宴。

68、對(duì)于Objective-C您觉,你認(rèn)為它最大的優(yōu)點(diǎn)和最大的不足是什么

最大的優(yōu)點(diǎn)是它的運(yùn)行時(shí)特性拙寡,不足是沒(méi)有命名空間,對(duì)于命名沖突顾犹,可以使用長(zhǎng)命名法或特殊前綴解決倒庵,如果是引入的第三方庫(kù)之間的命名沖突,可以

對(duì)項(xiàng)目buildsetting里的other linker flags進(jìn)行修改(第三方靜態(tài)庫(kù)引用者修改)

Bulding Setting里設(shè)置的other linker flags添加的有-Objc炫刷,而-Objc得作用就是將加載的靜態(tài)庫(kù)中的分類(lèi)一并加載到程序的可執(zhí)行文件擎宝,如果不添加這個(gè)參數(shù),很有可能會(huì)出現(xiàn)selector not recognized問(wèn)題浑玛,主要是找不到分類(lèi)定義的方法绍申。
-Objc添加后就會(huì)出現(xiàn)多個(gè)靜態(tài)庫(kù)定義同樣的方法、全局變量等顾彰,然后就會(huì)出現(xiàn)上面的問(wèn)題duplicate symbol极阅。

69、NSOperationQueue

你用過(guò)NSOperationQueue么涨享?如果用過(guò)或者了解的話筋搏,你為什么要使用NSOperationQueue,實(shí)現(xiàn)了什么厕隧?請(qǐng)描述它和G.C.D的區(qū)別和類(lèi)似的地方(提示:可以從兩者的實(shí)現(xiàn)機(jī)制和適用范圍來(lái)描述)奔脐。

使用NSOperationQueue用來(lái)管理子類(lèi)化的NSOperation對(duì)象,控制其線程并發(fā)數(shù)目吁讨。GCD和NSOperation都可以實(shí)現(xiàn)對(duì)線程的管理髓迎,區(qū)別是 NSOperation和NSOperationQueue是多線程的面向?qū)ο蟪橄蟆?
項(xiàng)目中使用NSOperation的優(yōu)點(diǎn)是NSOperation是對(duì)線程的高度抽象,在項(xiàng)目中使用它建丧,會(huì)使項(xiàng)目的程序結(jié)構(gòu)更好排龄,子類(lèi)化NSOperation的設(shè)計(jì)思路,是具有面向?qū)ο蟮膬?yōu)點(diǎn)(復(fù)用翎朱、封裝)橄维,使得實(shí)現(xiàn)是多線程支持,而接口簡(jiǎn)單拴曲,建議在復(fù)雜項(xiàng)目中使用挣郭。

項(xiàng)目中使用GCD的優(yōu)點(diǎn)是GCD本身非常簡(jiǎn)單、易用疗韵,對(duì)于不復(fù)雜的多線程操作兑障,會(huì)節(jié)省代碼量,而B(niǎo)lock參數(shù)的使用,會(huì)是代碼更為易讀流译,建議在簡(jiǎn)單項(xiàng)目中使用逞怨。

70、程序內(nèi)存分區(qū)

程序內(nèi)存分區(qū)
以下是比較常用的五分區(qū)方式福澡,當(dāng)然也不排除網(wǎng)上有其他的分區(qū)方式叠赦。


棧
棧的大小在編譯時(shí)就已經(jīng)確定了,一般是2M革砸;棧是一塊從高到低地址的連續(xù)區(qū)域除秀,存放臨時(shí)變量和執(zhí)行函數(shù)時(shí)的內(nèi)存等。棧內(nèi)存分配分為動(dòng)態(tài)和靜態(tài)算利,靜態(tài)如自動(dòng)變量(局部變量)等册踩,動(dòng)態(tài)如alloc等。

堆
堆是從低到高地址的不連續(xù)區(qū)域效拭,類(lèi)似鏈表暂吉;用來(lái)存放malloc或new申請(qǐng)的內(nèi)存。

全局/靜態(tài)
存放靜態(tài)/全局變量缎患;全局區(qū)細(xì)分為未初始化/初始化區(qū)慕的。

常量
存放常量;程序中使用的常量會(huì)到常量區(qū)獲取挤渔。
可以看看這個(gè)例子來(lái)理解一下肮街。

...int a;//a在全局未初始化區(qū)int a = 10;//a在全局初始化區(qū) 10在常量區(qū)static int a = 10;//a在靜態(tài)區(qū) 10在常量區(qū)//程序入口int main(...) {   int a = 10;//a在棧區(qū) 10在常量區(qū)
   static int a = 10;//a在靜態(tài)區(qū) 10在常量區(qū)
   char *a = (char *)malloc(10); //a在棧區(qū) malloc后的內(nèi)存在堆區(qū)
   ...
}
代碼
存放二進(jìn)制代碼,運(yùn)行程序就是執(zhí)行代碼判导,代碼要執(zhí)行就要加載進(jìn)內(nèi)存(RAM運(yùn)行內(nèi)存)嫉父。

71、指針函數(shù) / 函數(shù)指針 / Block

指針函數(shù)

C語(yǔ)言的概念骡楼;本質(zhì)是函數(shù),返回指針稽鞭。

char *fun() {    char *p = "";    return p;
}

函數(shù)指針

C語(yǔ)言的概念鸟整;本質(zhì)是指針,指向函數(shù)朦蕴。

int fun(int a,int b) {    return a + b;
}int (*func)(int,int);
func = fun;
func(1,2);//3

Block

OC語(yǔ)言的概念篮条;表示一個(gè)代碼塊,OC中視為對(duì)象吩抓;挺像C函數(shù)指針的涉茧。

//typedeftypedef int (^SumBlock)(int a,int b);
SumBlock sumBlock = ^(int a,int b) {    return a + b;
};
sumBlock(1,2);//3//普通
 int (^sumBlock)(int a,int b) = ^(int a,int b) {    return a + b;
};
sumBlock(1,2);//3

72、iOS類(lèi)和結(jié)構(gòu)體有什么區(qū)別

1:類(lèi)指針賦值時(shí)只是復(fù)制了地址疹娶,結(jié)構(gòu)體是復(fù)制內(nèi)容伴栓;
2:類(lèi)不能有同名同參數(shù)個(gè)數(shù)的方法,結(jié)構(gòu)體可以;
3:結(jié)構(gòu)體方法實(shí)現(xiàn)編譯時(shí)就確定了钳垮,類(lèi)方法實(shí)現(xiàn)可動(dòng)態(tài)改變惑淳;
4:內(nèi)存分配不一樣,結(jié)構(gòu)體在棧饺窿,類(lèi)在堆歧焦;
5:結(jié)構(gòu)體可以多重繼承,類(lèi)只能單繼承肚医。

73绢馍、線程安全方法

線程安全:多線程環(huán)境下保證數(shù)據(jù)的完整性。

隊(duì)列

把操作放入隊(duì)列線性執(zhí)行肠套,可用GCD和NSOperationQueue舰涌。

鎖/信號(hào)量

用鎖/信號(hào)量形成操作互斥。

讓操作原子化

讓操作原子執(zhí)行糠排,系統(tǒng)提供了一些原子執(zhí)行的方法舵稠。

了解更多

iOS-線程安全

74、NSOperationQueue和GCD區(qū)別聯(lián)系

區(qū)別

NSOperationQueue沒(méi)有串行/并發(fā)隊(duì)列入宦,但可以設(shè)置最大并發(fā)數(shù)哺徊;
NSOperationQueue支持方法和block,GCD只支持block乾闰;
NSOperationQueue可以暫停/取消操作落追;
NSOperationQueue支持更多的功能,比如KVO和自定義操作涯肩;
NSOperationQueue可以設(shè)置操作的優(yōu)先級(jí)轿钠,GCD只能設(shè)置隊(duì)列的優(yōu)先級(jí)。

聯(lián)系

提供的功能是相似的病苗;
NSOperationQueue是GCD的封裝疗垛。

75、對(duì)程序性能的優(yōu)化你有什么建議?

1.使用復(fù)用機(jī)制
2.盡可能設(shè)置 View 為不透明
3.避免臃腫的 XIB 文件
4.不要阻塞主線程
5.圖片尺寸匹配 UIImageView硫朦,避免巨大圖片
6.選擇合適的容器
8.View 的復(fù)用和懶加載機(jī)制
9.緩存  服務(wù)器的響應(yīng)信息(response)贷腕、 圖片、計(jì)算值咬展。比如:UITableView 的 row heights泽裳。
10.關(guān)于圖形繪制、減少離屏渲染(設(shè)置圓角和陰影的時(shí)候可以選用繪制的方法)
11.處理 Memory Warnings
在 AppDelegate 中實(shí)現(xiàn) - [AppDelegate applicationDidReceiveMemoryWarning:] 代理方法破婆。
在 UIViewController 中重載 didReceiveMemoryWarning 方法涮总。
監(jiān)聽(tīng) UIApplicationDidReceiveMemoryWarningNotification 通知。
12.復(fù)用高開(kāi)銷(xiāo)的對(duì)象
14.優(yōu)化 UITableView
通過(guò)正確的設(shè)置 reuseIdentifier 來(lái)重用 Cell祷舀。
盡量減少不必要的透明 View瀑梗。
盡量避免漸變效果烹笔、圖片拉伸和離屏渲染。
當(dāng)不同的行的高度不一樣時(shí)夺克,盡量緩存它們的高度值箕宙。
如果 Cell 展示的內(nèi)容來(lái)自網(wǎng)絡(luò),確保用異步加載的方式來(lái)獲取數(shù)據(jù)铺纽,并且緩存服務(wù)器的 response柬帕。
使用 shadowPath 來(lái)設(shè)置陰影效果。
盡量減少 subview 的數(shù)量狡门,對(duì)于 subview 較多并且樣式多變的 Cell陷寝,可以考慮用異步繪制或重寫(xiě) drawRect。
盡量?jī)?yōu)化 - [UITableView tableView:cellForRowAtIndexPath:] 方法中的處理邏輯其馏,如果確實(shí)要做一些處理凤跑,可以考慮做一次,緩存結(jié)果叛复。
選擇合適的數(shù)據(jù)結(jié)構(gòu)來(lái)承載數(shù)據(jù)仔引,不同的數(shù)據(jù)結(jié)構(gòu)對(duì)不同操作的開(kāi)銷(xiāo)是存在差異的。
對(duì)于 rowHeight褐奥、sectionFooterHeight咖耘、sectionHeaderHeight 盡量使用常量。
15.選擇合適的數(shù)據(jù)存儲(chǔ)方式
在 iOS 中可以用來(lái)進(jìn)行數(shù)據(jù)持有化的方案包括:
NSUserDefaults撬码。只適合用來(lái)存小數(shù)據(jù)儿倒。
XML、JSON呜笑、Plist 等文件夫否。JSON 和 XML 文件的差異在「選擇正確的數(shù)據(jù)格式」已經(jīng)說(shuō)過(guò)了。
使用 NSCoding 來(lái)存檔叫胁。NSCoding 同樣是對(duì)文件進(jìn)行讀寫(xiě)凰慈,所以它也會(huì)面臨必須加載整個(gè)文件才能繼續(xù)的問(wèn)題。
使用 SQLite 數(shù)據(jù)庫(kù)驼鹅∥⑽剑可以配合 FMDB 使用。數(shù)據(jù)的相對(duì)文件來(lái)說(shuō)還是好處很多的谤民,比如可以按需取數(shù)據(jù)堰酿、不用暴力查找等等疾宏。
使用 CoreData张足。也是數(shù)據(jù)庫(kù)技術(shù),跟 SQLite 的性能差異比較小坎藐。但是 CoreData 是一個(gè)對(duì)象圖譜模型为牍,顯得更面向?qū)ο蠛甙螅籗QLite 就是常規(guī)的 DBMS。
16.減少應(yīng)用啟動(dòng)時(shí)間
快速啟動(dòng)應(yīng)用對(duì)于用戶來(lái)說(shuō)可以留下很好的印象碉咆。尤其是第一次使用時(shí)抖韩。
保證應(yīng)用快速啟動(dòng)的指導(dǎo)原則:
盡量將啟動(dòng)過(guò)程中的處理分拆成各個(gè)異步處理流,比如:網(wǎng)絡(luò)請(qǐng)求疫铜、數(shù)據(jù)庫(kù)訪問(wèn)茂浮、數(shù)據(jù)解析等等。
避免臃腫的 XIB 文件壳咕,因?yàn)樗鼈儠?huì)在你的主線程中進(jìn)行加載席揽。重申:Storyboard 沒(méi)這個(gè)問(wèn)題,放心使用谓厘。
注意:在測(cè)試程序啟動(dòng)性能的時(shí)候幌羞,最好用與 Xcode 斷開(kāi)連接的設(shè)備進(jìn)行測(cè)試。因?yàn)?watchdog 在使用 Xcode 進(jìn)行調(diào)試的時(shí)候是不會(huì)啟動(dòng)的竟稳。
17.使用 Autorelease Pool (內(nèi)存釋放池)
18.imageNamed 和 imageWithContentsOfFile属桦,imageName會(huì)緩存圖片

76、NSURLConnection 和NSURLSession 的區(qū)別是 么? NSURLProtocol是做什么的?

1.下載
NSURLConnection下載文件時(shí)他爸,先是將整個(gè)文件下載到內(nèi)存聂宾,然后再寫(xiě)入到沙盒,如果文件比較大讲逛,就會(huì)出現(xiàn)內(nèi)存暴漲的情況亏吝。
而使用NSURLSessionDownloadTask下載文件,會(huì)默認(rèn)下載到沙盒中的tem文件中盏混,不會(huì)出現(xiàn)內(nèi)存暴漲的情況蔚鸥,但是在下載完成后會(huì)把tem中的臨時(shí)文件刪除,需要在初始化任務(wù)方法時(shí)许赃,在completionHandler回調(diào)中增加保存文件的代碼
2.請(qǐng)求方法的控制
NSURLConnection實(shí)例化對(duì)象止喷,實(shí)例化開(kāi)始,默認(rèn)請(qǐng)求就發(fā)送(同步發(fā)送),不需要調(diào)用start方法混聊。而cancel可以停止請(qǐng)求的發(fā)送弹谁,停止后不能繼續(xù)訪問(wèn),需要?jiǎng)?chuàng)建新的請(qǐng)求句喜。
NSURLSession有三個(gè)控制方法预愤,取消(cancel)、暫停(suspend)咳胃、繼續(xù)(resume)植康,暫停以后可以通過(guò)繼續(xù)恢復(fù)當(dāng)前的請(qǐng)求任務(wù)。
使用NSURLSession進(jìn)行斷點(diǎn)下載更加便捷.
NSURLSession的構(gòu)造方法(sessionWithConfiguration:delegate:delegateQueue)中有一個(gè)NSURLSessionConfiguration類(lèi)的參數(shù)可以設(shè)置配置信息展懈,其決定了cookie销睁,安全和高速緩存策略供璧,最大主機(jī)連接數(shù),資源管理冻记,網(wǎng)絡(luò)超時(shí)等配置睡毒。NSURLConnection不能進(jìn)行這個(gè)配置,相比較與NSURLConnection依賴與一個(gè)全局的配置對(duì)象冗栗,缺乏靈活性而言演顾,NSURLSession有很大的改進(jìn)

77、如果項(xiàng)目開(kāi)始容錯(cuò)處理沒(méi)做隅居?如何防止攔截潛在的崩潰偶房?

例:

1、category給類(lèi)添加方法用來(lái)替換掉原本存在潛在崩潰的方法军浆。

2棕洋、利用runtime方法交換技術(shù),將系統(tǒng)方法替換成類(lèi)添加的新方法乒融。

3掰盘、利用異常的捕獲來(lái)防止程序的崩潰,并且進(jìn)行相應(yīng)的處理赞季。

總結(jié):

1愧捕、不要過(guò)分相信服務(wù)器返回的數(shù)據(jù)會(huì)永遠(yuǎn)的正確。

2申钩、在對(duì)數(shù)據(jù)處理上次绘,要進(jìn)行容錯(cuò)處理,進(jìn)行相應(yīng)判斷之后再處理數(shù)據(jù)撒遣,這是一個(gè)良好的編程習(xí)慣邮偎。

78、容錯(cuò)處理你們一般是注意哪些义黎?

在團(tuán)隊(duì)協(xié)作開(kāi)發(fā)當(dāng)中禾进,由于每個(gè)團(tuán)隊(duì)成員的水平不一,很難控制代碼的質(zhì)量廉涕,保證代碼的健壯性泻云,經(jīng)常會(huì)發(fā)生由于后臺(tái)返回異常數(shù)據(jù)造成app崩潰閃退的情況,為了避免這樣的情況項(xiàng)目中做一些容錯(cuò)處理狐蜕,顯得格外重要宠纯,極大程度上降低了因?yàn)閿?shù)據(jù)容錯(cuò)不到位產(chǎn)生崩潰閃退的概率。

例如:

1.字典

2.數(shù)組层释;

3.野指針婆瓜;

4.NSNull   @"{\"value\": null}";  這種json解析出來(lái)的時(shí)候,NSNull如果去執(zhí)行方法湃累,就會(huì) unrecognized selector

等~

79勃救、內(nèi)存泄漏可能會(huì)出現(xiàn)的幾種原因,聊聊你的看法治力?

第一種可能:第三方框架不當(dāng)使用蒙秒;

第二種可能:block循環(huán)引用;

第三種可能:delegate循環(huán)引用宵统;

第四種可能:NSTimer循環(huán)引用 如 和 VC的循環(huán)引用

第五種可能:非OC對(duì)象內(nèi)存處理

第六種可能:地圖類(lèi)處理

第七種可能:大次數(shù)循環(huán)內(nèi)存暴漲



追問(wèn)一:非OC對(duì)象如何處理晕讲?

非OC對(duì)象,其需要手動(dòng)執(zhí)行釋放操作例:CGImageRelease(ref)马澈,否則會(huì)造成大量的內(nèi)存泄漏導(dǎo)致程序崩潰瓢省。

其他的對(duì)于CoreFoundation框架下的某些對(duì)象或變量需要手動(dòng)釋放踩衩、C語(yǔ)言代碼中的malloc等需要對(duì)應(yīng)free椰于。

80、常用鎖有以下幾種:

1.@synchronized 關(guān)鍵字加鎖

2. NSLock 對(duì)象鎖

3. NSCondition

4. NSConditionLock 條件鎖

5. NSRecursiveLock 遞歸鎖

6. pthread_mutex 互斥鎖(C語(yǔ)言)

7. dispatch_semaphore 信號(hào)量實(shí)現(xiàn)加鎖(GCD)

8. OSSpinLock

9.pthread_rwlock

10.POSIX Conditions

11.os_unfair_lock

追問(wèn)一:自旋和互斥對(duì)比臣疑?

自旋鎖和互斥鎖

相同點(diǎn):都能保證同一時(shí)間只有一個(gè)線程訪問(wèn)共享資源涤伐。都能保證線程安全馒胆。

不同點(diǎn):

互斥鎖:如果共享數(shù)據(jù)已經(jīng)有其他線程加鎖了,線程會(huì)進(jìn)入休眠狀態(tài)等待鎖凝果。一旦被訪問(wèn)的資源被解鎖祝迂,則等待資源的線程會(huì)被喚醒。

自旋鎖:如果共享數(shù)據(jù)已經(jīng)有其他線程加鎖了器净,線程會(huì)以死循環(huán)的方式等待鎖型雳,一旦被訪問(wèn)的資源被解鎖,則等待資源的線程會(huì)立即執(zhí)行山害。

自旋鎖的效率高于互斥鎖纠俭。

使用自旋鎖時(shí)要注意:

由于自旋時(shí)不釋放CPU,因而持有自旋鎖的線程應(yīng)該盡快釋放自旋鎖浪慌,否則等待該自旋鎖的線程會(huì)一直在哪里自旋柑晒,這就會(huì)浪費(fèi)CPU時(shí)間。

持有自旋鎖的線程在sleep之前應(yīng)該釋放自旋鎖以便其他可以獲得該自旋鎖眷射。內(nèi)核編程中匙赞,如果持有自旋鎖的代碼sleep了就可能導(dǎo)致整個(gè)系統(tǒng)掛起。

使用任何鎖都需要消耗系統(tǒng)資源(內(nèi)存資源和CPU時(shí)間)妖碉,這種資源消耗可以分為兩類(lèi):

1.建立鎖所需要的資源

2.當(dāng)線程被阻塞時(shí)所需要的資源

追問(wèn)二:用C/OC/C++涌庭,任選其一,實(shí)現(xiàn)自旋或互斥欧宜?口述即可坐榆!

cpp實(shí)現(xiàn):


兩種鎖的加鎖原理:

互斥鎖:線程會(huì)從sleep(加鎖)——>running(解鎖),過(guò)程中有上下文的切換冗茸,cpu的搶占席镀,信號(hào)的發(fā)送等開(kāi)銷(xiāo)匹中。

自旋鎖:線程一直是running(加鎖——>解鎖),死循環(huán)檢測(cè)鎖的標(biāo)志位豪诲,機(jī)制不復(fù)雜顶捷。

81、優(yōu)化你是從哪幾方面著手

一屎篱、首頁(yè)啟動(dòng)速度

啟動(dòng)過(guò)程中做的事情越少越好(盡可能將多個(gè)接口合并)

不在UI線程上作耗時(shí)的操作(數(shù)據(jù)的處理在子線程進(jìn)行服赎,處理完通知主線程刷新節(jié)目)

在合適的時(shí)機(jī)開(kāi)始后臺(tái)任務(wù)(例如在用戶指引節(jié)目就可以開(kāi)始準(zhǔn)備加載的數(shù)據(jù))

盡量減小包的大小

優(yōu)化方法:

量化啟動(dòng)時(shí)間

啟動(dòng)速度模塊化

輔助工具(友盟,聽(tīng)云交播,F(xiàn)lurry)

二重虑、頁(yè)面瀏覽速度

json的處理(iOS 自帶的NSJSONSerialization,Jsonkit秦士,SBJson)

數(shù)據(jù)的分頁(yè)(后端數(shù)據(jù)多的話缺厉,就要分頁(yè)返回,例如網(wǎng)易新聞隧土,或者 微博記錄)

數(shù)據(jù)壓縮(大數(shù)據(jù)也可以壓縮返回芽死,減少流量,加快反應(yīng)速度)

內(nèi)容緩存(例如網(wǎng)易新聞的最新新聞列表都是要緩存到本地次洼,從本地加載关贵,可以緩存到內(nèi)存,或者數(shù)據(jù)庫(kù)卖毁,根據(jù)情況而定)

延時(shí)加載tab(比如app有5個(gè)tab揖曾,可以先加載第一個(gè)要顯示的tab,其他的在顯示時(shí)候加載亥啦,按需加載)

算法的優(yōu)化(核心算法的優(yōu)化炭剪,例如有些app 有個(gè) 聯(lián)系人姓名用漢語(yǔ)拼音的首字母排序)

三、操作流暢度優(yōu)化:

Tableview 優(yōu)化(tableview cell的加載優(yōu)化)

ViewController加載優(yōu)化(不同view之間的跳轉(zhuǎn)翔脱,可以提前準(zhǔn)備好數(shù)據(jù))

四奴拦、數(shù)據(jù)庫(kù)的優(yōu)化:

數(shù)據(jù)庫(kù)設(shè)計(jì)上面的重構(gòu)

查詢語(yǔ)句的優(yōu)化

分庫(kù)分表(數(shù)據(jù)太多的時(shí)候,可以分不同的表或者庫(kù))

五届吁、服務(wù)器端和客戶端的交互優(yōu)化:

客戶端盡量減少請(qǐng)求

服務(wù)端盡量做多的邏輯處理

服務(wù)器端和客戶端采取推拉結(jié)合的方式(可以利用一些同步機(jī)制)

通信協(xié)議的優(yōu)化错妖。(減少報(bào)文的大小)

電量使用優(yōu)化(盡量不要使用后臺(tái)運(yùn)行)

82疚沐、怎么防止別人動(dòng)態(tài)在你程序生成代碼暂氯?怎么防止反編譯?

(這題是聽(tīng)錯(cuò)了面試官的意思)

面試官意思是怎么防止別人反編譯你的app亮蛔?

1.本地?cái)?shù)據(jù)加密

iOS應(yīng)用防反編譯加密技術(shù)之一:對(duì)NSUserDefaults痴施,sqlite存儲(chǔ)文件數(shù)據(jù)加密,保護(hù)帳號(hào)和關(guān)鍵信息

2.URL編碼加密

iOS應(yīng)用防反編譯加密技術(shù)之二:對(duì)程序中出現(xiàn)的URL進(jìn)行編碼加密,防止URL被靜態(tài)分析

3.網(wǎng)絡(luò)傳輸數(shù)據(jù)加密

iOS應(yīng)用防反編譯加密技術(shù)之三:對(duì)客戶端傳輸數(shù)據(jù)提供加密方案辣吃,有效防止通過(guò)網(wǎng)絡(luò)接口的攔截獲取數(shù)據(jù)

4.方法體动遭,方法名高級(jí)混淆

iOS應(yīng)用防反編譯加密技術(shù)之四:對(duì)應(yīng)用程序的方法名和方法體進(jìn)行混淆,保證源碼被逆向后無(wú)法解析代碼

5.程序結(jié)構(gòu)混排加密

iOS應(yīng)用防反編譯加密技術(shù)之五:對(duì)應(yīng)用程序邏輯結(jié)構(gòu)進(jìn)行打亂混排神得,保證源碼可讀性降到最低

84厘惦、你理解的多線程?

1.可能會(huì)追問(wèn)循头,每種多線程基于什么語(yǔ)言?

2.生命周期是如何管理炎疆?

3.你更傾向于哪種卡骂?追問(wèn)至現(xiàn)在常用的兩種你的看法是?

第一種:pthread

.特點(diǎn):

1)一套通用的多線程API

2)適用于Unix\Linux\Windows等系統(tǒng)

3)跨平臺(tái)\可移植

4)使用難度大

b.使用語(yǔ)言:c語(yǔ)言

c.使用頻率:幾乎不用

d.線程生命周期:由程序員進(jìn)行管理

第二種:NSThread

a.特點(diǎn):

1)使用更加面向?qū)ο?
2)簡(jiǎn)單易用形入,可直接操作線程對(duì)象

b.使用語(yǔ)言:OC語(yǔ)言

c.使用頻率:偶爾使用

d.線程生命周期:由程序員進(jìn)行管理

第三種:GCD

a.特點(diǎn):

1)旨在替代NSThread等線程技術(shù)

2)充分利用設(shè)備的多核(自動(dòng))

b.使用語(yǔ)言:C語(yǔ)言

c.使用頻率:經(jīng)常使用

d.線程生命周期:自動(dòng)管理

第四種:NSOperation

a.特點(diǎn):

1)基于GCD(底層是GCD)

2)比GCD多了一些更簡(jiǎn)單實(shí)用的功能

3)使用更加面向?qū)ο?
b.使用語(yǔ)言:OC語(yǔ)言

c.使用頻率:經(jīng)常使用

d.線程生命周期:自動(dòng)管理

多線程的原理

同一時(shí)間全跨,CPU只能處理1條線程,只有1條線程在工作(執(zhí)行)

多線程并發(fā)(同時(shí))執(zhí)行亿遂,其實(shí)是CPU快速地在多條線程之間調(diào)度(切換)

如果CPU調(diào)度線程的時(shí)間足夠快浓若,就造成了多線程并發(fā)執(zhí)行的假象

思考:如果線程非常非常多,會(huì)發(fā)生什么情況蛇数?

CPU會(huì)在N多線程之間調(diào)度挪钓,CPU會(huì)累死,消耗大量的CPU資源

每條線程被調(diào)度執(zhí)行的頻次會(huì)降低(線程的執(zhí)行效率降低)

多線程的優(yōu)點(diǎn)

能適當(dāng)提高程序的執(zhí)行效率

能適當(dāng)提高資源利用率(CPU耳舅、內(nèi)存利用率)

多線程的缺點(diǎn)

開(kāi)啟線程需要占用一定的內(nèi)存空間(默認(rèn)情況下碌上,主線程占用1M,子線程占用512KB)浦徊,如果開(kāi)啟大量的線程馏予,會(huì)占用大量的內(nèi)存空間,降低程序的性能

線程越多盔性,CPU在調(diào)度線程上的開(kāi)銷(xiāo)就越大

程序設(shè)計(jì)更加復(fù)雜:比如線程之間的通信霞丧、多線程的數(shù)據(jù)共享

你更傾向于哪一種?

傾向于GCD:

GCD

技術(shù)是一個(gè)輕量的冕香,底層實(shí)現(xiàn)隱藏的神奇技術(shù)蛹尝,我們能夠通過(guò)GCD和block輕松實(shí)現(xiàn)多線程編程,有時(shí)候悉尾,GCD相比其他系統(tǒng)提供的多線程方法更加有效箩言,當(dāng)然,有時(shí)候GCD不是最佳選擇焕襟,另一個(gè)多線程編程的技術(shù)

NSOprationQueue 讓我們能夠?qū)⒑笈_(tái)線程以隊(duì)列方式依序執(zhí)行陨收,并提供更多操作的入口,這和 GCD 的實(shí)現(xiàn)有些類(lèi)似。

這種類(lèi)似不是一個(gè)巧合务漩,在早期拄衰,MacOX

與 iOS 的程序都普遍采用Operation

Queue來(lái)進(jìn)行編寫(xiě)后臺(tái)線程代碼,而之后出現(xiàn)的GCD技術(shù)大體是依照前者的原則來(lái)實(shí)現(xiàn)的饵骨,而隨著GCD的普及翘悉,在iOS 4 與 MacOS X

10.6以后,Operation Queue的底層實(shí)現(xiàn)都是用GCD來(lái)實(shí)現(xiàn)的居触。

那這兩者直接有什么區(qū)別呢妖混?

1.    GCD是底層的C語(yǔ)言構(gòu)成的API,而NSOperationQueue及相關(guān)對(duì)象是Objc的對(duì)象轮洋。在GCD中制市,在隊(duì)列中執(zhí)行的是由block構(gòu)成的任務(wù),這是一個(gè)輕量級(jí)的數(shù)據(jù)結(jié)構(gòu)弊予;而Operation作為一個(gè)對(duì)象祥楣,為我們提供了更多的選擇;

2.    在NSOperationQueue中汉柒,我們可以隨時(shí)取消已經(jīng)設(shè)定要準(zhǔn)備執(zhí)行的任務(wù)(當(dāng)然误褪,已經(jīng)開(kāi)始的任務(wù)就無(wú)法阻止了)碾褂,而GCD沒(méi)法停止已經(jīng)加入queue的block(其實(shí)是有的正塌,但需要許多復(fù)雜的代碼)渡八;

3.    NSOperation能夠方便地設(shè)置依賴關(guān)系屎鳍,我們可以讓一個(gè)Operation依賴于另一個(gè)Operation,這樣的話盡管兩個(gè)Operation處于同一個(gè)并行隊(duì)列中问裕,但前者會(huì)直到后者執(zhí)行完畢后再執(zhí)行粮宛;

4.    我們能將KVO應(yīng)用在NSOperation中巍杈,可以監(jiān)聽(tīng)一個(gè)Operation是否完成或取消筷畦,這樣子能比GCD更加有效地掌控我們執(zhí)行的后臺(tái)任務(wù);

5.    在NSOperation中逆航,我們能夠設(shè)置NSOperation的priority優(yōu)先級(jí)因俐,能夠使同一個(gè)并行隊(duì)列中的任務(wù)區(qū)分先后地執(zhí)行,而在GCD中澳眷,我們只能區(qū)分不同任務(wù)隊(duì)列的優(yōu)先級(jí)境蔼,如果要區(qū)分block任務(wù)的優(yōu)先級(jí),也需要大量的復(fù)雜代碼罐监;

6.    我們能夠?qū)SOperation進(jìn)行繼承弓柱,在這之上添加成員變量與成員方法矢空,提高整個(gè)代碼的復(fù)用度屁药,這比簡(jiǎn)單地將block任務(wù)排入執(zhí)行隊(duì)列更有自由度,能夠在其之上添加更多自定制的功能缭嫡。

總的來(lái)說(shuō)妇蛀,Operation

queue

提供了更多你在編寫(xiě)多線程程序時(shí)需要的功能讥耗,并隱藏了許多線程調(diào)度蔼卡,線程取消與線程優(yōu)先級(jí)的復(fù)雜代碼雇逞,為我們提供簡(jiǎn)單的API入口塘砸。從編程原則來(lái)說(shuō),一般我們需要盡可能的使用高等級(jí)女轿、封裝完美的API蛉迹,在必須時(shí)才使用底層API。但是我認(rèn)為當(dāng)我們的需求能夠以更簡(jiǎn)單的底層代碼完成的時(shí)候珍策,簡(jiǎn)潔的GCD或許是個(gè)更好的選擇攘宙,而Operation

queue 為我們提供能更多的選擇。

傾向于:NSOperation

NSOperation相對(duì)于GCD:

1链方,NSOperation擁有更多的函數(shù)可用祟蚀,具體查看api前酿。NSOperationQueue 是在GCD基礎(chǔ)上實(shí)現(xiàn)的淹仑,只不過(guò)是GCD更高一層的抽象匀借。

2,在NSOperationQueue中是鬼,可以建立各個(gè)NSOperation之間的依賴關(guān)系均蜜。

3杖爽,NSOperationQueue支持KVO慰安√汛埽可以監(jiān)測(cè)operation是否正在執(zhí)行(isExecuted)查刻、是否結(jié)束(isFinished),是否取消(isCanceld)

4佃延,GCD 只支持FIFO 的隊(duì)列履肃,而NSOperationQueue可以調(diào)整隊(duì)列的執(zhí)行順序(通過(guò)調(diào)整權(quán)重)封锉。NSOperationQueue可以方便的管理并發(fā)烘浦、NSOperation之間的優(yōu)先級(jí)。

使用NSOperation的情況:各個(gè)操作之間有依賴關(guān)系握侧、操作需要取消暫停品擎、并發(fā)管理、控制操作之間優(yōu)先級(jí)秀菱,限制同時(shí)能執(zhí)行的線程數(shù)量.讓線程在某時(shí)刻停止/繼續(xù)等。

使用GCD的情況:一般的需求很簡(jiǎn)單的多線程操作脊串,用GCD都可以了琼锋,簡(jiǎn)單高效。

從編程原則來(lái)說(shuō)念赶,一般我們需要盡可能的使用高等級(jí)旗吁、封裝完美的API很钓,在必須時(shí)才使用底層API。

當(dāng)需求簡(jiǎn)單袁稽,簡(jiǎn)潔的GCD或許是個(gè)更好的選擇,而Operation queue 為我們提供能更多的選擇歹撒。

85、SD原理以及最大支持多少個(gè)下載數(shù)迈着?

6

86市框、runtime動(dòng)態(tài)創(chuàng)建一個(gè)類(lèi)枫振,需要注意什么斧拍?

了解一些如何動(dòng)態(tài)構(gòu)建類(lèi)

87肆汹、有一個(gè)很長(zhǎng)字符串浪册,你用什么算法搜索到abc的位置?

1厚者、暴力匹配

2、KMP查找

3蝙昙、后綴樹(shù)

88、代碼文件編譯生成過(guò)程烈拒,編譯和鏈接有什么區(qū)別,鏈接做了什么事情

將預(yù)處理生成的文件吨铸,經(jīng)過(guò)詞法分析、語(yǔ)法分析房维、語(yǔ)義分析以及優(yōu)化后編譯成若干個(gè)目標(biāo)模塊“⒊茫可以理解為將高級(jí)語(yǔ)言翻譯為計(jì)算機(jī)可以理解的二進(jìn)制代碼飞几,即機(jī)器語(yǔ)言。

由鏈接程序?qū)⒕幾g后形成的一組目標(biāo)模塊以及它們所需要的庫(kù)函數(shù)鏈接在一起卵史,形成一個(gè)完整的載入模型。鏈接主要解決模塊間的相互引用問(wèn)題忧设。分為地址和空間分配,符號(hào)解析和重定位幾個(gè)步驟。

在編譯階段生成目標(biāo)文件時(shí)刘陶,會(huì)暫時(shí)擱置那些外部引用,而這些外部引用就是在鏈接時(shí)進(jìn)行確定的纷责,鏈接器在鏈接時(shí),會(huì)根據(jù)符號(hào)名稱(chēng)去相應(yīng)模塊中尋找對(duì)應(yīng)符號(hào)满钟。待符號(hào)確定之后,鏈接器會(huì)重寫(xiě)之前那些未確定的符號(hào)的地址,這個(gè)過(guò)程就是重定位讲竿。鏈接一般分為靜態(tài)鏈接、載入時(shí)動(dòng)態(tài)鏈接以及運(yùn)行時(shí)動(dòng)態(tài)鏈接三種迈嘹。

89、用C語(yǔ)言實(shí)現(xiàn)一個(gè)通知流程,說(shuō)思路即可挑豌!


90、A B 線程執(zhí)行到一半去執(zhí)行C線程,用OC和C各自怎么實(shí)現(xiàn)徘键!

wait notify


dispatch_wait

dispatch_notify

91、快排的原理

選定一個(gè)基準(zhǔn)數(shù)它呀,左右根據(jù)基準(zhǔn)數(shù)進(jìn)行調(diào)控下隧,小的往基準(zhǔn)數(shù)左邊放,小的往右邊放,遞歸執(zhí)行

92拷淘、C語(yǔ)言中strlen和sizeof的區(qū)別

sizeof是求數(shù)據(jù)類(lèi)型所占的空間大小,而strlen是求字符串的長(zhǎng)度

93邓厕、推送的原理

1补君、 注冊(cè):為應(yīng)用程序申請(qǐng)消息推送服務(wù)。此時(shí)你的設(shè)備會(huì)向APNs服務(wù)器發(fā)送注冊(cè)請(qǐng)求叽掘。
2、 APNs服務(wù)器接受請(qǐng)求,并將deviceToken返給你設(shè)備上的應(yīng)用程序
3膛薛、客戶端應(yīng)用程序?qū)eviceToken發(fā)送給后臺(tái)服務(wù)器程序雅任,后臺(tái)接收并儲(chǔ)存乌企。
4拳喻、 后臺(tái)服務(wù)器向APNs服務(wù)器發(fā)送推送消息
5、 APNs服務(wù)器將消息發(fā)給deviceToken對(duì)應(yīng)設(shè)備上的應(yīng)用程序

94亚亲、一個(gè)頁(yè)面可以由幾個(gè)控制器共同管理嗎


95腐缤、項(xiàng)目上線或者版本迭代捌归,有過(guò)被拒嗎?是什么原因岭粤?怎么解決惜索?


99剃浇、請(qǐng)說(shuō)明并比較以下關(guān)鍵詞:atomic, nonatomic

atomic修飾的對(duì)象會(huì)保證setter和getter的完整性巾兆,任何線程對(duì)其訪問(wèn)都可以得到一個(gè)完整的初始化后的對(duì)象。

因?yàn)橐WC操作完成虎囚,所以速度慢角塑。它比nonatomic安全,但也并不是絕對(duì)的線程安全淘讥,例如多個(gè)線程同時(shí)調(diào)用set和get就會(huì)導(dǎo)致獲得的對(duì)象值不一樣圃伶。絕對(duì)的線程安全就要用關(guān)鍵詞synchronized。

atomic只是get set線程安全适揉,不代表就一定線程安全了

nonatomic修飾的對(duì)象不保證setter和getter的完整性留攒,所以多個(gè)線程對(duì)它進(jìn)行訪問(wèn),它可能會(huì)返回未初始化的對(duì)象嫉嘀。正因?yàn)槿绱肆堆萢tomic快,但也是線程不安全的剪侮。

100拭宁、你平時(shí)做過(guò)什么有技術(shù)難點(diǎn)的東西洛退,然后怎么解決的

異步繪制的問(wèn)題

性能優(yōu)化

項(xiàng)目?jī)?yōu)化

代碼優(yōu)化

自動(dòng)化打包

地圖、視頻


寫(xiě)一套對(duì)應(yīng)的VC內(nèi)存泄露檢查機(jī)制杰标,控件子線程調(diào)用的檢查機(jī)制

101兵怯、聊一聊你之前公司的項(xiàng)目


MVC架構(gòu),分為腔剂,基礎(chǔ)庫(kù)(基礎(chǔ)組件媒区、網(wǎng)絡(luò)請(qǐng)求、基礎(chǔ)category)層掸犬、中間層(路由層袜漩、網(wǎng)絡(luò)擴(kuò)展層)、業(yè)務(wù)層湾碎、展示層

除開(kāi)獨(dú)立性高的業(yè)務(wù)宙攻,其他的業(yè)務(wù)層和展示層在主工程,基礎(chǔ)層和中間層在pod資源中


Swift介褥、OC混編項(xiàng)目座掘,需要兼顧Swift和OC帶來(lái)的編譯問(wèn)題,加入Swift后柔滔,新業(yè)務(wù)都使用Swift開(kāi)發(fā)溢陪,盡量少耦合老代碼。

使用pod為項(xiàng)目管理工具廊遍、fastlane為自動(dòng)打包工具

分發(fā)系統(tǒng)式 基于ruby和bash腳本寫(xiě)的內(nèi)部自動(dòng)化打包分發(fā)系統(tǒng)

102嬉愧、Swift和OC混編遇到了什么問(wèn)題

1、編譯速度問(wèn)題 5分鐘變?yōu)?10分鐘

2喉前、經(jīng)常丟失斷點(diǎn)没酣、丟失提示、llbd打印信息錯(cuò)誤等

這種情況卵迂,請(qǐng)仔細(xì)檢查你的橋接文件:項(xiàng)目名-Bridging-Header裕便,是否導(dǎo)入了第三方庫(kù)。若導(dǎo)入了第三方庫(kù)见咒,則該庫(kù)是否是以Cocoapods來(lái)管理的偿衰,比如AFNetWorking是通過(guò) Cocoapods 管理的,那么在橋接文件中改览,你應(yīng)該

@import AFNetWorking;

而不是 import "AFNetWorking.h"下翎,或者以這種#import導(dǎo)入該三方的其他文件


3、命名空間的問(wèn)題

103宝当、Swift 引入后 編譯優(yōu)化的一些思考

1. 盡可能的移除pch中的文件视事、XX-Swift.h文件千萬(wàn)不要圖方便放到pch文件中,不然每次編譯都需要全局編譯

2. 盡可能的減少Objective-C與Swift的混編庆揩,減小bridge文件的大小俐东、通過(guò)模塊化跌穗,實(shí)現(xiàn)OC與Swift之間的隔離 通過(guò)路由的方式進(jìn)行模塊通信,降低耦合度虏辫,路由中間件也可以減少業(yè)務(wù)中頭文件的頻繁交叉蚌吸、繁復(fù)引用,降低耦合性

3. 模塊頭文件引用以@import or import <> 庫(kù)引用的方式

4. 通過(guò)中間件減少業(yè)務(wù)中頭文件的交叉砌庄、繁復(fù)引用羹唠,降低耦合性

5. 通過(guò)將第三方庫(kù)、基礎(chǔ)組件二進(jìn)制化減少編譯時(shí)間鹤耍,把很少改動(dòng)或者基本不會(huì)改的庫(kù)編譯成二進(jìn)制framework

6. 組件化的時(shí)候注意組件之間的依賴關(guān)系

- 業(yè)務(wù)組件盡可能不依賴業(yè)務(wù)組件肉迫,如果依賴關(guān)系過(guò)強(qiáng)验辞,就需要考慮是否業(yè)務(wù)拆分有問(wèn)題
- 業(yè)務(wù)組件只依賴基礎(chǔ)組件與第三方庫(kù)
- 基礎(chǔ)組件不依賴業(yè)務(wù)組件
- 基礎(chǔ)組件盡量不依賴基礎(chǔ)組件 

104稿黄、項(xiàng)目?jī)?yōu)化的一些思考

項(xiàng)目的優(yōu)化分為編譯優(yōu)化 和 運(yùn)行優(yōu)化


編譯優(yōu)化指的是 優(yōu)化方向是優(yōu)化我們的開(kāi)發(fā)過(guò)程,例如編譯速度跌造,代碼效率杆怕,迭代效率,擴(kuò)展性等

運(yùn)行優(yōu)化指的是 優(yōu)化方向是app的運(yùn)行壳贪,例如陵珍,列表流暢度、交互體驗(yàn)违施、網(wǎng)絡(luò)延時(shí)等等


編譯優(yōu)化:

Swift編譯速度慢的原因:

1互纯、本身方法實(shí)現(xiàn)耗時(shí)太多:在xcode中開(kāi)啟編譯時(shí)長(zhǎng)檢查,方法編譯時(shí)間超出設(shè)置值就會(huì)有黃色警告

2磕蒲、過(guò)多的編譯器類(lèi)型檢查:例如過(guò)多的optation 類(lèi)型

3留潦、頭文件的引用問(wèn)題,盡可能的移除pch中的文件辣往、XX-Swift.h文件千萬(wàn)不要圖方便放到pch文件中兔院,不然每次編譯都需要全局編譯

4、swift工程引用OC pod庫(kù)  不需要通過(guò)橋文件 直接import對(duì)應(yīng)的庫(kù)名稱(chēng)站削,也盡量少在bridge文件中對(duì)OC庫(kù)的頭文件進(jìn)行引用坊萝,影響Xcode編譯效率,同時(shí)會(huì)導(dǎo)致lldb調(diào)試問(wèn)題和斷點(diǎn)問(wèn)題

5、 pod庫(kù)太多:把一些穩(wěn)定的 不需要變更的庫(kù)许起,打成二進(jìn)制包


懶加載的使用

105十偶、iOS系統(tǒng)框架介紹

image

107、如何攔截AFNetworking园细,我希望在請(qǐng)求發(fā)出去之前添加一些頭部信息

runtime覆蓋request方法惦积,但是很蠢

108、日志上報(bào)珊肃,錯(cuò)誤日志上報(bào)荣刑,業(yè)界有哪些方法 案例

exception catch

信號(hào)異常 catch

109馅笙、一個(gè)app進(jìn)入后臺(tái)之后如何喚起

app沒(méi)死可以通過(guò)通知

app已死可以通過(guò)VoIP

110、如果沒(méi)有API 沒(méi)有百度厉亏,你要怎么解決一個(gè)問(wèn)題董习,有實(shí)際處理過(guò)類(lèi)似情況么,比如把一個(gè)1M的文件盡可能的壓縮


110爱只、100個(gè)隨機(jī)數(shù)字皿淋,想要找到最大值,時(shí)間復(fù)雜度是恬试?

O(n)

111窝趣、數(shù)據(jù)庫(kù)都有哪些類(lèi)型

112、iOS虛擬內(nèi)存的使用

115训柴、什么是ABI哑舒?

應(yīng)用程序二進(jìn)制接口,應(yīng)用程序與操作系統(tǒng)之間幻馁,一個(gè)應(yīng)用和它的庫(kù)之間或者應(yīng)用的組成部分之間的低接口洗鸵。

API 表示的時(shí)源代碼和庫(kù)之間的接口,ABI允許編譯好的目標(biāo)代碼在使用賤人ABI的系統(tǒng)中無(wú)需改動(dòng)就能運(yùn)行

116仗嗦、REST膘滨、HTTP、JSON是什么稀拐?

RESTful api Representational State Transfer 資源表現(xiàn)層狀態(tài)轉(zhuǎn)化架構(gòu)

(1)每一個(gè)URI代表一種資源火邓;
(2)客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層德撬;
(3)客戶端通過(guò)四個(gè)HTTP動(dòng)詞铲咨,對(duì)服務(wù)器端資源進(jìn)行操作,實(shí)現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"砰逻。

117鸣驱、delegate解決了什么問(wèn)題,Notification與它有什么不同蝠咆?

delegate  一對(duì)一的通信原理踊东,完成消息回調(diào)

Notification 是一對(duì)多,與對(duì)象之間無(wú)需建立直接關(guān)系

118刚操、LLVM與Clang的區(qū)別闸翅?

Clang 是編譯器前端

Clang 的作用是 語(yǔ)法、語(yǔ)義分析器菊霜,生成中間代碼

LLVM是編譯器后端

LLVM的作用是代碼優(yōu)化器和后端生成目標(biāo)程序

從宏觀上來(lái)說(shuō)坚冀,LLVM包含了Clang

119、Class鉴逞、objc的區(qū)別是什么记某?

objc為實(shí)例對(duì)象司训,表示的時(shí)通過(guò)類(lèi)構(gòu)建的一個(gè)實(shí)例本身,實(shí)例對(duì)象是一個(gè)objc_object 類(lèi)型的結(jié)構(gòu)體液南,包含一個(gè) Class類(lèi)型的isa屬性 用于表明其所屬的類(lèi)

Class為類(lèi)對(duì)象壳猜,表示的是類(lèi)本身

120、不通過(guò)繼承滑凉,代碼復(fù)用(共享)的方式有哪些

protocol 協(xié)議

extension 擴(kuò)展 

runtime

122统扳、在一個(gè)app中間有一個(gè)button,在你手觸摸屏幕點(diǎn)擊后畅姊,到這個(gè)button收到點(diǎn)擊事件咒钟,中間發(fā)生了什么

響應(yīng)鏈大概有以下幾個(gè)步驟

1. 設(shè)備將touch到的UITouch和UIEvent對(duì)象打包, 放到當(dāng)前活動(dòng)的Application的事件隊(duì)列中
2. 單例的UIApplication會(huì)從事件隊(duì)列中取出觸摸事件并傳遞給單例UIWindow
3. UIWindow使用hitTest:withEvent:方法查找touch操作的所在的視圖view

RunLoop這邊我大概講一下

1. 主線程的RunLoop被喚醒
2. 通知Observer,處理Timer和Source 0
3. Springboard接受touch event之后轉(zhuǎn)給App進(jìn)程中
4. RunLoop處理Source 1若未,Source1 就會(huì)觸發(fā)回調(diào)姨谷,并調(diào)用_UIApplicationHandleEventQueue() 進(jìn)行應(yīng)用內(nèi)部的分發(fā)赁还。
5. RunLoop處理完畢進(jìn)入睡眠堂淡,此前會(huì)釋放舊的autorelease pool并新建一個(gè)autorelease pool

123忘衍、main()之前的過(guò)程有哪些重贺?

1倘感、系統(tǒng)先讀取App的可執(zhí)行文件(Mach-O文件)牲证,獲取到dyld的路徑军洼,并加載dyld(動(dòng)態(tài)庫(kù)鏈接程序)玫荣。

2甚淡、dyld去初始化運(yùn)行環(huán)境、開(kāi)啟緩存策略(冷熱啟動(dòng))捅厂、加載依賴庫(kù)(讀取文件贯卦、驗(yàn)證、注冊(cè)到系統(tǒng)核心)焙贷、我們的可執(zhí)行文件撵割、鏈接依賴庫(kù),并調(diào)用每個(gè)依賴庫(kù)的初始化方法辙芍。

3啡彬、在上一步runtime被初始化,當(dāng)所有的依賴庫(kù)初始化后故硅,程序可執(zhí)行文件進(jìn)行初始化庶灿,這個(gè)時(shí)候runtime會(huì)對(duì)項(xiàng)目中的所有類(lèi)進(jìn)行類(lèi)結(jié)構(gòu)初始化,然后調(diào)用所有類(lèi)的+load方法吃衅。

1往踢、runtime初始化方法 _objc_init 中最后注冊(cè)了兩個(gè)通知:

map_images: 主要是在鏡像加載進(jìn)內(nèi)容后對(duì)其二進(jìn)制內(nèi)容進(jìn)行解析,初始化里面的類(lèi)結(jié)構(gòu)等

load_images: 主要是調(diào)用call_load_methods 按照繼承層次依次調(diào)用Class的 +load方法 然后是Category的+ load方法徘层。(call_load_methods 調(diào)用load 是通過(guò)方法地址直接調(diào)用的load方法峻呕,并不是通過(guò)消息機(jī)制利职,這就是為什么分類(lèi)中的load方法并不會(huì)覆蓋主類(lèi)以及其他同主類(lèi)的分類(lèi)里的load 方法實(shí)現(xiàn)了。)

2瘦癌、runtime 調(diào)用項(xiàng)目中所有的load方法時(shí)眼耀,所有的類(lèi)的結(jié)構(gòu)已經(jīng)初始化了,此時(shí)在load方法中可以使用任何類(lèi)創(chuàng)建實(shí)例并給他們發(fā)送消息。

4佩憾、最后dyld返回main函數(shù)地址哮伟,main函數(shù)被調(diào)用。dyld會(huì)緩存上一次把信息加載內(nèi)存的緩存妄帘,所以第二次比第一次啟動(dòng)快一點(diǎn)

124楞黄、block為什么防止引用循環(huán)為什么要外部weak 內(nèi)部 strong

因?yàn)閎lock截獲self之后self屬于block結(jié)構(gòu)體中的一個(gè)由__strong修飾的屬性會(huì)強(qiáng)引用self, 所以需要使用__weak修飾的weakSelf防止循環(huán)引用抡驼。
block使用的__strong修飾的weakSelf是為了在block(可以理解為函數(shù))生命周期中self不會(huì)提前釋放鬼廓。strongSelf實(shí)質(zhì)是一個(gè)局部變量(在block這個(gè)“函數(shù)”里面的局部變量),當(dāng)block執(zhí)行完畢就會(huì)釋放自動(dòng)變量strongSelf致盟,不會(huì)對(duì)self進(jìn)行一直進(jìn)行強(qiáng)引用碎税。

125、iOS 中內(nèi)省的幾個(gè)方法馏锡?class方法和objc_getClass方法有什么區(qū)別?

內(nèi)省方法
判斷對(duì)象類(lèi)型:
-(BOOL) isKindOfClass: 判斷是否是這個(gè)類(lèi)或者這個(gè)類(lèi)的子類(lèi)的實(shí)例
-(BOOL) isMemberOfClass: 判斷是否是這個(gè)類(lèi)的實(shí)例
判斷對(duì)象or類(lèi)是否有這個(gè)方法
-(BOOL) respondsToSelector: 判讀實(shí)例是否有這樣方法
+(BOOL) instancesRespondToSelector: 判斷類(lèi)是否有這個(gè)方法

object_getClass(obj)返回的是obj中的isa指針雷蹂;而[obj class]則分兩種情況:一是當(dāng)obj為實(shí)例對(duì)象時(shí),[obj  class]中class是實(shí)例方法:- (Class)class杯道,返回的obj對(duì)象中的isa指針匪煌;二是當(dāng)obj為類(lèi)對(duì)象(包括元類(lèi)和根類(lèi)以及根元類(lèi))時(shí),調(diào)用的是類(lèi)方法:+ (Class)class党巾,返回的結(jié)果為其本身萎庭。

126、在運(yùn)行時(shí)創(chuàng)建類(lèi)的方法objc_allocateClassPair的方法名尾部為什么是pair(成對(duì)的意思)齿拂?

另一半就是meta-class

127驳规、一個(gè)int變量被__block修飾與否的區(qū)別?

沒(méi)有修飾署海,被block捕獲吗购,是值拷貝。
使用__block修飾,會(huì)生成一個(gè)結(jié)構(gòu)體叹侄,復(fù)制int的引用地址巩搏。達(dá)到修改數(shù)據(jù)。

128趾代、如何取消系統(tǒng)默認(rèn)的KVO并手動(dòng)觸發(fā)(給KVO的觸發(fā)設(shè)定條件:改變的值符合某個(gè)條件時(shí)再觸發(fā)KVO)贯底?

前面我們已經(jīng)領(lǐng)教了KVO的實(shí)現(xiàn),那如何取消系統(tǒng)的自動(dòng)KVO呢

實(shí)現(xiàn)NSObject的方法,過(guò)濾我們需要過(guò)濾的key
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    if ([key isEqualToString:@"name"]) {
        return NO;
    }
    return [super automaticallyNotifiesObserversForKey:key];
}

實(shí)現(xiàn)自己的KVO邏輯
- (void)setName:(NSString *)name {
    [self willChangeValueForKey:@"name"];
    _name = name;
    [self didChangeValueForKey:@"name"];
}

130禽捆、什么是中間人攻擊

攻擊者在請(qǐng)求和響應(yīng)傳輸途中笙什,攔截并篡改內(nèi)容。

SSL 證書(shū)欺騙攻擊流程大概如下:

截獲客戶端與服務(wù)器通信的通道
然后在 SSL 建立連接的時(shí)候胚想,進(jìn)行中間人攻擊
將自己偽裝成客戶端琐凭,獲取到服務(wù)器真實(shí)有效的 CA 證書(shū)(非對(duì)稱(chēng)加密的公鑰)
將自己偽裝成服務(wù)器,獲取到客服端的之后通信的密鑰(對(duì)稱(chēng)加密的密鑰)
有了證書(shū)和密鑰就可以監(jiān)聽(tīng)之后通信的內(nèi)容了

133浊服、了解內(nèi)聯(lián)函數(shù)么统屈?

OC中使用inline,主要是為了提高函數(shù)調(diào)用的效率
使用例子:
static inline NSString * imageURLKeyForState(UIControlState state) {
    return [NSString stringWithFormat:@"image_%lu", (unsigned long)state];
}


我們通常會(huì)發(fā)現(xiàn)牙躺,inline 會(huì)有 static來(lái)修飾愁憔,表示在當(dāng)前文件中應(yīng)用,如 static b, 在其它文件中也可以出現(xiàn)static b.不會(huì)導(dǎo)致重名的錯(cuò)誤.
inline和函數(shù)
1.inline函數(shù)避免了普通函數(shù)的,在匯編時(shí)必須調(diào)用call的缺點(diǎn):取消了函數(shù)的參數(shù)壓棧,減少了調(diào)用的開(kāi)銷(xiāo),提高效率.所以執(zhí)行速度確比一般函數(shù)的執(zhí)行速度要快.
2.集成了宏的優(yōu)點(diǎn),使用時(shí)直接用代碼替換(像宏一樣)
inline和宏
1.避免了宏的缺點(diǎn):需要預(yù)編譯.因?yàn)閕nline內(nèi)聯(lián)函數(shù)也是函數(shù),不需要預(yù)編譯.
2.編譯器在調(diào)用一個(gè)內(nèi)聯(lián)函數(shù)時(shí)孽拷,會(huì)首先檢查它的參數(shù)的類(lèi)型吨掌,保證調(diào)用正確。然后進(jìn)行一系列的相關(guān)檢查脓恕,就像對(duì)待任何一個(gè)真正的函數(shù)一樣膜宋。這樣就消除了它的隱患和局限性。
3.可以使用所在類(lèi)的保護(hù)成員及私有成員炼幔。
inline 說(shuō)明
1.內(nèi)聯(lián)函數(shù)只是我們向編譯器提供的申請(qǐng),編譯器不一定采取inline形式調(diào)用函數(shù).
2.內(nèi)聯(lián)函數(shù)不能承載大量的代碼.如果內(nèi)聯(lián)函數(shù)的函數(shù)體過(guò)大,編譯器會(huì)自動(dòng)放棄內(nèi)聯(lián).
3.內(nèi)聯(lián)函數(shù)內(nèi)不允許使用循環(huán)語(yǔ)句或開(kāi)關(guān)語(yǔ)句
4.內(nèi)聯(lián)函數(shù)的定義須在調(diào)用之前秋茫。

135、iOS SDK中的那些設(shè)計(jì)模式的使用


KVO 觀察者模式

單例模式 NSFileManager 江掩、 UIApplication

代理委托模式:UITableViewDelegate

適配器模式:類(lèi)似中間件的構(gòu)建学辱,當(dāng)接入SDK的時(shí)候,適配器模式可以起到隔離并適配的作用

裝飾模式: 比如 category

抽象工廠模式:讓外部無(wú)需知道工廠內(nèi)部的任何變動(dòng)

137环形、鏈表和數(shù)組的區(qū)別是什么?插入和查詢的時(shí)間復(fù)雜度分別是多少衙傀?

數(shù)組是一段連續(xù)的內(nèi)存地址抬吟,鏈表是無(wú)序的,根據(jù)指針來(lái)指向下一個(gè)內(nèi)存地址

數(shù)組查詢指定位置的元素很方便统抬,但是插入和刪除需要移動(dòng)火本,不如鏈表方便,查找O(1) 添加刪除 O(n)

鏈表的插入刪除元素相對(duì)數(shù)組較為簡(jiǎn)單聪建,不需要移動(dòng)元素钙畔,且較為容易實(shí)現(xiàn)長(zhǎng)度擴(kuò)充,但是尋找某個(gè)元素較為困難金麸; 查找O(n), 添加刪除O(1)

138擎析、哈希表是如何實(shí)現(xiàn)的?如何解決地址沖突挥下?

散列表(Hash table揍魂,也叫哈希表)桨醋,是根據(jù)關(guān)鍵碼值(Key-Value)而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。


通過(guò)把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪問(wèn)記錄现斋,以加快查找的速度喜最。查詢時(shí)間復(fù)雜度O(1)


地址沖突處理:

地址沖突是什么? 
實(shí)際上是由數(shù)組和鏈表的方式組合實(shí)現(xiàn)的庄蹋。我們哈希出來(lái)的key會(huì)放置在數(shù)組的某個(gè)位置瞬内,這個(gè)時(shí)候如果有其他元素哈希結(jié)果也是這個(gè)位置的時(shí)候,且兩個(gè)key并不一樣限书。這就是地址沖突虫蝶。

1、再哈希蔗包,重新進(jìn)行一次全部的哈希秉扑,常見(jiàn)于需要擴(kuò)容的時(shí)候,翻倍擴(kuò)容并重新哈希

2调限、當(dāng)key相同的時(shí)候舟陆,會(huì)再數(shù)組后面鏈接一個(gè)鏈表并把值存入

136、面向?qū)ο蟮脑O(shè)計(jì)原則

面向?qū)ο笤O(shè)計(jì)的六個(gè)設(shè)計(jì)原則:

縮寫(xiě) 英文名稱(chēng) 中文名稱(chēng)
SRP Single Responsibility Principle 單一職責(zé)原則
OCP Open Close Principle 開(kāi)閉原則
LSP Liskov Substitution Principle 里氏替換原則
LoD Law of Demeter ( Least Knowledge Principle) 迪米特法則(最少知道原則)
ISP Interface Segregation Principle 接口分離原則
DIP Dependency Inversion Principle 依賴倒置原則

通常所說(shuō)的SOLID(上方表格縮寫(xiě)的首字母耻矮,從上到下)設(shè)計(jì)原則沒(méi)有包含本篇介紹的迪米特法則

141秦躯、NSCache 和 NSDictionary

如何選擇存緩存數(shù)據(jù)結(jié)構(gòu)

當(dāng)系統(tǒng)資源將要耗盡時(shí),它可以自動(dòng)刪減緩存裆装。
NSCache還會(huì)先行刪減“最久未使用的”(lease recently used)對(duì)象踱承。
NSCache 并不會(huì)“拷貝”鍵,而是會(huì)“保留”它哨免。NSCache對(duì)象不拷貝鍵的原因在于:很多時(shí)候茎活,鍵都是有不支持拷貝操作的對(duì)象來(lái)充當(dāng)?shù)摹R虼俗镣伲琋SCache 不會(huì)自動(dòng)拷貝鍵载荔,所以說(shuō),在健不支持拷貝操作的情況下采桃,該類(lèi)用起來(lái)比字典更方便懒熙。
NSCache是線程安全的。而NSDictionary則絕不具備此優(yōu)勢(shì)普办,意思就是:在開(kāi)發(fā)者自己不編寫(xiě)加鎖代碼的前提下工扎,多個(gè)線程便可以同時(shí)訪問(wèn)NSCache.

142、iOS圖片內(nèi)存占用由什么決定

圖片顯示占用內(nèi)存大小 = 圖片的寬度 乘以 圖片的高度 乘以 顏色 RGBA 占用的4個(gè)字節(jié);

還有色域等會(huì)影響

143衔蹲、索引的作用肢娘、索引的優(yōu)缺點(diǎn)

作用優(yōu)點(diǎn)

因?yàn)樗饕梢源蟠筇岣叩男阅堋?
第1通過(guò)唯一性索引可以保證數(shù)據(jù)庫(kù)表中每一行數(shù)據(jù)的唯一性。

第2可以大大加快數(shù)據(jù)的檢索速度。這也是創(chuàng)建索引最主要的原因蔬浙。

缺點(diǎn)

第1 創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間猪落,這種時(shí)間隨著數(shù)據(jù)量的增加而增加。

第2 實(shí)際上索引也是一張表畴博,該表保存了主鍵與索引字段.索引需要占物理空間笨忌,

144、NSMutableArray的實(shí)現(xiàn)原理

http://www.reibang.com/p/3c77756a86ab

__NSArrayM 用了環(huán)形緩沖區(qū) (circular buffer)俱病。這個(gè)數(shù)據(jù)結(jié)構(gòu)相當(dāng)簡(jiǎn)單官疲,只是比常規(guī)數(shù)組或緩沖區(qū)復(fù)雜點(diǎn)。環(huán)形緩沖區(qū)的內(nèi)容能在到達(dá)任意一端時(shí)繞向另一端亮隙。環(huán)形緩沖區(qū)有一些非惩举欤酷的屬性。尤其是溢吻,除非緩沖區(qū)滿了维费,否則在任意一端插入或刪除均不會(huì)要求移動(dòng)任何內(nèi)存。

__NSArrayM 從不減少它的緩沖區(qū)大小

145促王、編譯鏈接

預(yù)處理犀盟、編譯(詞法分析、語(yǔ)法分析蝇狼、靜態(tài)分析阅畴、中間代碼生成)、匯編迅耘、鏈接(生成 Executable 可執(zhí)行文件)

146贱枣、NSProxy & NSObject

NSProxy是一個(gè)虛類(lèi),實(shí)現(xiàn)了NSObject協(xié)議颤专,可以用于處理weakProxy問(wèn)題

146纽哥、繼續(xù)了解

大數(shù)字符串相加

合并鏈表

反轉(zhuǎn)數(shù)組、 旋轉(zhuǎn)數(shù)組

非遞歸二叉樹(shù)

快速排序

反轉(zhuǎn)二叉樹(shù)

147栖秕、 Oc和Swift的消息派發(fā)的差異

動(dòng)態(tài)派發(fā)都是一樣的昵仅,注意 動(dòng)態(tài)派發(fā)是不支持值類(lèi)型的

1、4種派發(fā)機(jī)制累魔,而不是兩種(靜態(tài)和動(dòng)態(tài)):

1. 內(nèi)聯(lián)(inline) (最快)    內(nèi)聯(lián)是指在編譯期把每一處方法調(diào)用替換為直接執(zhí)行方法內(nèi)部的代碼,可以幫助你避免運(yùn)行時(shí)方法調(diào)用的時(shí)間開(kāi)銷(xiāo)够滑。
2. 靜態(tài)派發(fā) (Static Dispatch)
3. 函數(shù)表派發(fā) (Virtual Dispatch)
4. 動(dòng)態(tài)派發(fā) (Dynamic Dispatch)(最慢)


OC默認(rèn)支持動(dòng)態(tài)派發(fā)垦写,多態(tài)的形式為開(kāi)發(fā)人員提供靈活性,例如重寫(xiě)彰触,但是同樣動(dòng)態(tài)的查找需要運(yùn)行時(shí)的開(kāi)銷(xiāo)

2梯投、消息派發(fā),KVO,runtime方法查找

swift 要通過(guò) @objc 分蓖、 dynamic 橋接OC 的runtime尔艇,間接實(shí)現(xiàn),可以通過(guò)SIL中間文件判斷派發(fā)方式

Swift 中的動(dòng)態(tài)派發(fā)和 OC 中的動(dòng)態(tài)派發(fā)類(lèi)似么鹤,在運(yùn)行時(shí)程序會(huì)根據(jù)被調(diào)用的方法的名字去內(nèi)存中的方法表中查表终娃,找到方法的實(shí)現(xiàn)并執(zhí)行。


3蒸甜、swift的靜態(tài)派發(fā)

要求方法內(nèi)部代碼對(duì)編譯器透明棠耕,運(yùn)行時(shí)不允許更改,這樣編譯器才可以保證我們運(yùn)行的時(shí)候不需要查表可以直接跳轉(zhuǎn)到方法代碼執(zhí)行柠新。值類(lèi)型滿足靜態(tài)派發(fā)的要求

148窍荧、內(nèi)存碎片、 內(nèi)存對(duì)齊

內(nèi)存碎片產(chǎn)生的原因:

內(nèi)部碎片:當(dāng)一個(gè)進(jìn)程不能完全使用分給他的固定內(nèi)存區(qū)域時(shí)產(chǎn)生內(nèi)存碎片

比如多次內(nèi)存分配后釋放了 2  + 1 內(nèi)存恨憎,但是兩個(gè)內(nèi)存塊不連續(xù)蕊退,所以你沒(méi)法申請(qǐng)一個(gè) 3 的內(nèi)存



處理方案,內(nèi)存頁(yè)憔恳,比如:每?jī)蓚€(gè)連續(xù)內(nèi)存組成一個(gè)內(nèi)存頁(yè)瓤荔,進(jìn)程申請(qǐng)的最小單位為頁(yè)面 多頁(yè)面一起申請(qǐng)組合使用,但是問(wèn)題就是內(nèi)存頁(yè)會(huì)存在資源浪費(fèi)



外部碎片:某些未分配的連續(xù)內(nèi)存區(qū)域太小喇嘱,不能滿足進(jìn)程的內(nèi)存分配需求而不能被利用的內(nèi)存區(qū)域

149茉贡、緩存淘汰算法

FIFO  LRU(最近最少使用,最近一段時(shí)間最少被訪問(wèn)的數(shù)據(jù)淘汰掉)   LFU(最不經(jīng)常使用者铜、基于最近訪問(wèn)頻率來(lái)進(jìn)行淘汰)   都適用于什么情況

LRU  這個(gè)緩存算法將最近使用的條目存放到靠近緩存頂部的位置腔丧。當(dāng)一個(gè)新條目被訪問(wèn)時(shí),LRU將它放置到緩存的頂部作烟。當(dāng)緩存達(dá)到極限時(shí)愉粤,較早之前訪問(wèn)的條目將從緩存底部開(kāi)始被移除。這里會(huì)使用到昂貴的算法拿撩,而且它需要記錄“年齡位”來(lái)精確顯示條目是何時(shí)被訪問(wèn)的衣厘。此外,當(dāng)一個(gè)LRU緩存算法刪除某個(gè)條目后压恒,“年齡位”將隨其他條目發(fā)生改變影暴。

LFU   最不經(jīng)常使用、基于最近訪問(wèn)頻率來(lái)進(jìn)行淘汰

命中率高一些

150探赫、 iOS渲染機(jī)制

render server

https://blog.csdn.net/u011342466/article/details/50918035

151型宙、 卡頓原理

動(dòng)畫(huà)中的presationLayer

152、

iOS IPC https://segmentfault.com/a/1190000002400329

153伦吠、互斥量妆兑、信號(hào)量

互斥量用于線程的互斥魂拦,信號(hào)量用于線程的同步。

這是互斥量和信號(hào)量的根本區(qū)別搁嗓,也就是互斥和同步之間的區(qū)別芯勘。

互斥:是指某一資源同時(shí)只允許一個(gè)訪問(wèn)者對(duì)其進(jìn)行訪問(wèn),具有唯一性和排它性腺逛。但互斥無(wú)法限制訪問(wèn)者對(duì)資源的訪問(wèn)順序荷愕,即訪問(wèn)是無(wú)序的。

同步:是指在互斥的基礎(chǔ)上(大多數(shù)情況)屉来,通過(guò)其它機(jī)制實(shí)現(xiàn)訪問(wèn)者對(duì)資源的有序訪問(wèn)路翻。在大多數(shù)情況下,同步已經(jīng)實(shí)現(xiàn)了互斥茄靠,特別是所有寫(xiě)入資源的情況必定是互斥的茂契。少數(shù)情況是指可以允許多個(gè)訪問(wèn)者同時(shí)訪問(wèn)資源

154、class_ro_t與class_rw_t的區(qū)別

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    class_rw_t *data() const {
        return bits.data();
    }
    
    
類(lèi)結(jié)構(gòu)中包含了class_data_bits_t結(jié)構(gòu)慨绳,這個(gè)結(jié)構(gòu)實(shí)際上上是由一個(gè)指針(class_rw_t *)和一些關(guān)于類(lèi)初始化狀態(tài)的的標(biāo)識(shí)組成


而class_rw_t結(jié)構(gòu)中又包含了一個(gè)const class_ro_t *類(lèi)型的指針實(shí)現(xiàn)

對(duì)比變量定義發(fā)現(xiàn)掉冶,class_ro_t結(jié)構(gòu)中與class_rw_t對(duì)應(yīng)的的主要成員變量都使用了base做區(qū)分,說(shuō)明class_ro_t的結(jié)構(gòu)更加貼近類(lèi)本身的結(jié)構(gòu),class_rw_t像是類(lèi)拓展出來(lái)的.


在關(guān)于類(lèi)的實(shí)現(xiàn)中,幾乎所有引用到class_ro_t變量的地方都是使用了const關(guān)鍵字做修飾,更像是一個(gè)靜態(tài)不愿意被外界修改的屬性;而引用到class_rw_t變量就沒(méi)有這樣的限制.

所以可以理解為class_ro_t存儲(chǔ)的是類(lèi)在編譯期就已經(jīng)確定的特性,而class_rw_t則是提供在運(yùn)行時(shí)進(jìn)行類(lèi)延展的能力.






155、- Category的實(shí)現(xiàn)原理脐雪,以及Category為什么只能加方法不能加成員變量厌小。

struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;
    struct method_list_t *classMethods;
    struct protocol_list_t *protocols;
    struct property_list_t *instanceProperties;
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
    
    protocol_list_t *protocolsForMeta(bool isMeta) {
        if (isMeta) return nullptr;
        else return protocols;
    }
};

分類(lèi)的結(jié)構(gòu)體中沒(méi)有成員變量,所以分類(lèi)是不允許添加成員變量的战秋。分類(lèi)中添加的屬性璧亚,并不會(huì)生成成員變量,只會(huì)有g(shù)et set 方法聲明脂信,需要自己實(shí)現(xiàn)癣蟋。 Category可以添加屬性,編譯并不會(huì)報(bào)錯(cuò)狰闪,但是并不會(huì)自動(dòng)生成成員變量及set/get方法疯搅。

成員變量是存放在實(shí)例對(duì)象中的,并且編譯的那一刻就已經(jīng)決定好了埋泵。而分類(lèi)是在運(yùn)行時(shí)才去加載的幔欧。那么我們就無(wú)法再程序運(yùn)行時(shí)將分類(lèi)的成員變量中添加到實(shí)例對(duì)象的結(jié)構(gòu)體中。因此分類(lèi)中不可以添加成員變量丽声。

  • 分類(lèi)的方法礁蔗,協(xié)議,屬性等是存放在categroy結(jié)構(gòu)體里面的雁社,那么他又是如何存儲(chǔ)在類(lèi)對(duì)象中的呢瘦麸?

分類(lèi)的實(shí)現(xiàn)原理是將category中的方法,屬性歧胁,協(xié)議數(shù)據(jù)放在category_t結(jié)構(gòu)體中滋饲,然后將結(jié)構(gòu)體內(nèi)的方法列表拷貝到類(lèi)對(duì)象的方法列表中。(runtime方法 attachLists memmove喊巍,memcpy)

分類(lèi)的對(duì)象方法存儲(chǔ)在哪屠缭? 類(lèi)方法呢?

分類(lèi)中的對(duì)象方法依然是存儲(chǔ)在類(lèi)對(duì)象中的崭参,同本類(lèi)對(duì)象方法在同一個(gè)地方呵曹,調(diào)用步驟也同調(diào)用對(duì)象方法一樣。如果是類(lèi)方法的話何暮,也同樣是存儲(chǔ)在元類(lèi)對(duì)象中奄喂。

rw->methods.attachLists(mlists, mcount),
rw->properties.attachLists(proplists, propcount),
rw->protocols.attachLists(protolists, protocount),
  • 分類(lèi)中l(wèi)oad方法不會(huì)覆蓋本類(lèi)的load方法,load方法是直接方法地址調(diào)用海洼,沒(méi)有通過(guò)消息機(jī)制跨新,本類(lèi)更早調(diào)用:

call_load_methods 里面在進(jìn)行的 call_class_loads() 然后再是 call_category_loads()

(*load_method)(cls, @selector(load)); 就是使用指針?lè)绞街苯诱{(diào)用load方法,不走 objc_msgSend方法

分類(lèi)和本類(lèi)都實(shí)現(xiàn)load方法坏逢,都會(huì)調(diào)用域帐,但是本類(lèi)更早。當(dāng)子類(lèi)沒(méi)有實(shí)現(xiàn)load方法時(shí)是整,不會(huì)去調(diào)用父類(lèi)的load方法肖揣。

  • 多個(gè)分類(lèi)時(shí)方法調(diào)用順序,按編譯順序浮入,最后編譯的最先調(diào)用龙优。

initialize就是如此,分類(lèi)的initialize方法會(huì)覆蓋本類(lèi)的initialize方法

父類(lèi)的initialize方法比子類(lèi)先執(zhí)行事秀,子類(lèi)沒(méi)有實(shí)現(xiàn)initialize方法時(shí)彤断,會(huì)調(diào)用父類(lèi)的initialize方法;放子類(lèi)實(shí)現(xiàn)initialize方法時(shí)會(huì)覆蓋父類(lèi)的initialize方法秽晚。

分類(lèi)方法是運(yùn)行時(shí)期間拷貝到類(lèi)對(duì)象方法列表瓦糟,isa指針找到方法列表先找到的就是分類(lèi)的方法。所以分類(lèi)會(huì)覆蓋本類(lèi)的方法赴蝇。

load 源碼調(diào)用路徑

_objc_init   初始化

load_images

prepare_load_methods
- schedule_class_load
- add_class_load
- add_category_to_loadable_list

call_load_methods
- call_class_loads
- call_category_loads

(*load_method)(cls, **@selector**(load)); 
initialize 源碼調(diào)用路徑

objc-msg-arm64.s
objc_msgSend

objc-runtime-new.mm
class_getInstanceMethod
lookUpImpOrNil
lookUpImpOrForward
_class_initialize
callInitialize
objc_msgSend(cls,SEL_initialize)

class結(jié)構(gòu)體:

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

分類(lèi)的信息最后是添加到本類(lèi)信息的前面的.所以如果分類(lèi)中有和本類(lèi)相同的方法,會(huì)優(yōu)先調(diào)用分類(lèi)的方法實(shí)現(xiàn)

拷貝分類(lèi)方法到類(lèi)對(duì)象菩浙,相同的方法怎么辦

156、OC向一個(gè)nil對(duì)象發(fā)送消息

objc_msgSend 第一個(gè)參數(shù)數(shù)self

objc_msgSend(id self, SEL op, ...)
  
會(huì)有指令直接判斷測(cè)試  self是否為空
  
如果傳遞給 objc_msgSend 的 self 參數(shù)是 nil句伶,該函數(shù)不會(huì)執(zhí)行有意義的操作劲蜻,直接返回。
  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末考余,一起剝皮案震驚了整個(gè)濱河市先嬉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌楚堤,老刑警劉巖疫蔓,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件含懊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡衅胀,警方通過(guò)查閱死者的電腦和手機(jī)岔乔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)滚躯,“玉大人雏门,你說(shuō)我怎么就攤上這事〉停” “怎么了茁影?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)丧凤。 經(jīng)常有香客問(wèn)我募闲,道長(zhǎng),這世上最難降的妖魔是什么息裸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任蝇更,我火速辦了婚禮,結(jié)果婚禮上呼盆,老公的妹妹穿的比我還像新娘年扩。我一直安慰自己,他們只是感情好访圃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布厨幻。 她就那樣靜靜地躺著,像睡著了一般腿时。 火紅的嫁衣襯著肌膚如雪况脆。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天批糟,我揣著相機(jī)與錄音格了,去河邊找鬼。 笑死徽鼎,一個(gè)胖子當(dāng)著我的面吹牛盛末,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播否淤,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼悄但,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了石抡?” 一聲冷哼從身側(cè)響起檐嚣,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啰扛,沒(méi)想到半個(gè)月后嚎京,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體嗡贺,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年挖藏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暑刃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡膜眠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溜嗜,到底是詐尸還是另有隱情宵膨,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布炸宵,位于F島的核電站辟躏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏土全。R本人自食惡果不足惜捎琐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望裹匙。 院中可真熱鬧瑞凑,春花似錦、人聲如沸概页。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惰匙。三九已至技掏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間项鬼,已是汗流浹背哑梳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绘盟,地道東北人鸠真。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像奥此,于是被迫代替她去往敵國(guó)和親弧哎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,103評(píng)論 1 32
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,146評(píng)論 30 470
  • OC語(yǔ)言基礎(chǔ) 1.類(lèi)與對(duì)象 類(lèi)方法 OC的類(lèi)方法只有2種:靜態(tài)方法和實(shí)例方法兩種 在OC中稚虎,只要方法聲明在@int...
    奇異果好補(bǔ)閱讀 4,274評(píng)論 0 11
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛(ài)閱讀 1,984評(píng)論 0 7
  • 九小時(shí) 五百四十分鐘 它們一樣 卻也不一樣 時(shí)針還沒(méi)瀏覽到全貌 分針已經(jīng)轉(zhuǎn)得很無(wú)聊 同一方天地中生長(zhǎng) 卻注定了各自...
    云端沒(méi)有地平線閱讀 176評(píng)論 0 0