題目引自 zhangferry — 快手iOS面經(jīng)丈积,此處根據(jù)自己理解做出解答記錄
一面
1. 用遞歸寫一個算法赤拒,計算從1到100的和跟继。
int fun(int x) {
if(x>1)
return x+fun(x-1); //
else
return x;
}
int main(int argc, const char * argv[]) {
int sum;
sum = fun(100);
printf("sum=%d\n",sum);
return 0;
}
// sum=5050
時間復(fù)雜度O(n)
胰丁,空間復(fù)雜度O(n)
非遞歸
時間復(fù)雜度O(n)
,空間復(fù)雜度O(1)
int fun(int n) {
int total = 0;
for (int i = 1; i <= n; i++) {
total += i;
}
return total;
}
等差數(shù)列公式
時間復(fù)雜度O(1)
腊瑟,空間復(fù)雜度O(1)
int fun(int n) {
return n * (1+n)/2;
}
遞歸優(yōu)缺點:
優(yōu)點是代碼易讀易懂
缺點是代碼效率低聚假,空間復(fù)雜度高,調(diào)用太深容易棧溢出
2. property的作用是什么闰非,有哪些關(guān)鍵詞膘格,分別是什么含義?
property
是一個屬性自動生成器财松,自動生成setter瘪贱、getter方法
常見屬性關(guān)鍵詞:atomic, nonatomic, assign, retain, strong, weak, copy, readonly, readwrite, unsafe_unretained, getter=, setter= 等。
默認屬性關(guān)鍵詞:繼承于NSObject類的對象:(atomic, strong), 非繼承于NSObject類的對象:(atomic, assign)
屬性意義:
atomic:原子性的辆毡,在執(zhí)行setter和getter方法時可以保證訪問變量的線程安全菜秦。
nonatomic:非原子性的,無法保證訪問變量的線程安全性舶掖,但是變量訪問效率會提高球昨。
assign:主要用于修飾非繼承于NSObject類型的對象,例如int, double, NSInteger等眨攘,當(dāng)該對象被其他對象引用時主慰,該對象的引用計數(shù)不會自加1。
retain:一般情況下等同于ARC環(huán)境下的strong修飾符鲫售,但是在修飾block對象時共螺,retain相當(dāng)于assign,而strong相當(dāng)于copy情竹。
strong:主要用于繼承于NSObject類的對象藐不,當(dāng)strong修飾的對象被其他對象引用時,引用計數(shù)會自加1秦效。
weak:主要用于繼承于NSObject類的對象雏蛮,當(dāng)weak修飾的對象被其他對象引用時,引用計數(shù)不會自加1棉安,且retainCount為0時底扳,指向該對象的指針將會置nil,指向堆棧的底部0x00000000贡耽,防止野指針的出現(xiàn)。
unsafe_unretained:主要用于繼承于NSObject類型的對象,當(dāng)retainCount為0時蒲赂,指向該對象的指針不會置nil阱冶,因此可能會出現(xiàn)野指針,但是效率方面會比weak要高滥嘴。
copy:主要適用于NSArray木蹬,NSDictionary,NSString若皱,Block等類型的對象镊叁,開辟一塊新的內(nèi)存存儲原來內(nèi)存中的元素,對象指針指向新內(nèi)存的地址走触。
readonly:只讀屬性
readwrite:讀寫屬性
getter =:修改讀屬性名稱
setter =:修改寫屬性名稱
關(guān)鍵詞:
readonly:只讀
assign:單純賦值(非對象類型使用)
retain:進行對象保持操作
strong:同retain晦譬,用于ARC
weak:不進行對象保持操作,同時訪問安全的互广,用于ARC
copy:復(fù)制對象 (生成副本進行賦值敛腌,但只適用于遵循NSCopying協(xié)議的對象)
nonatomic:非原子操作,非線程安全惫皱,主要使用
atomic:原子操作像樊,主要是在getter和setter方法里面加鎖,基本不用
3. 父類的property是如何查找的旅敷?
@interface Person : NSObject
{
NSObject *bbbbb;
}
@property (nonatomic, strong) NSObject *aaaaaa;
@end
@implementation Person
@end
@interface Teacher : Person
@end
@implementation Teacher
@end
clang編譯后
struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSObject *bbbbb;
NSObject *_aaaaaa;
};
struct Teacher_IMPL {
struct Person_IMPL Person_IVARS;
};
1.子類中的
propert_list
生棍、method_list
、ivar_list
并不包含父類
2.子類對象的_IMPL
包含父類的媳谁,所以應(yīng)該是通過Person_IMPL
查找的父類property
涂滴。
4. NSArray和NSDictionary如何選關(guān)鍵詞?
- 當(dāng)修飾可變類型的屬性時韩脑,如NSMutableArray氢妈、NSMutableDictionary、NSMutableString段多,用strong首量。
- 當(dāng)修飾不可變類型的屬性時,如NSArray进苍、NSDictionary加缘、NSString,用copy觉啊。
5. copy和mutableCopy有什么區(qū)別?深復(fù)制和淺復(fù)制是什么意思杠人,如何實現(xiàn)深復(fù)制宋下?
- 對于不可變對象,copy就是淺復(fù)制学歧,mutableCopy 就是深復(fù)制各吨。
- 對于可變對象,copy和mutableCopy都是深復(fù)制揭蜒。
- 不論是可變還是不可變對象,copy返回的對象都是不可變的屉更,mutableCopy返回的對象都是可變的。
- 容器類對象(NSArray偶垮,NSDictionary等):
不論是可變的還是不可變的,copy似舵,mutableCopy返回的容器類對象里所包含的對象的地址和之前都是一樣的,即容器內(nèi)對象都是淺復(fù)制砚哗。
6. 用runtime做過什么事情龙助?runtime中的方法交換是如何實現(xiàn)的?
- KVO監(jiān)聽屬性變化
- 動態(tài)方法解析時給類添加方法
- 消息轉(zhuǎn)發(fā)
- 方法交換
方法交換實現(xiàn)原理:
每個類都維護一個方法Method表蛛芥,Method包含SEL
和其對應(yīng)IMP
的信息提鸟,方法交換做的事情就是把SEL
和IMP
的對應(yīng)關(guān)系斷開,并和新的IMP
生成對應(yīng)關(guān)系仅淑。比如:ASel -> AImp称勋、BSel -> BImp,交換之后就是ASel -> BImp涯竟、BSel -> AImp赡鲜。
7. 講一下對KVC和KVO的理解?
- KVC:
- 通過
valueForKey:
和valueForKeyPath:
來取值,按照get<Key>
庐船,<key>
银酬,is<Key>
,_<key>
的順序查找方法筐钟。- 通過
setValueForKey:
和setValueForKeyPath:
來賦值揩瞪。按照set<Key>
,_set<Key>
的順序查找方法篓冲。- iOS13以前可以通過KVC獲取李破、設(shè)置系統(tǒng)屬性宠哄,iOS13以后被禁用。
- KVO:
- 利用
Runtime API
動態(tài)生成一個子類喷屋,并且讓對象的isa
指向這個全新的子類琳拨,當(dāng)修改對象的屬性時瞭恰,會調(diào)用如下方法:
Foundation
的_NSSetXXXValueAndNotify
函數(shù)
willChangeValueForKey:
父類原來的setter
didChangeValueForKey:
內(nèi)部會觸發(fā)監(jiān)聽器(Oberser)的監(jiān)聽方法(observeValueForKeyPath:ofObject:change:context:
)
如何手動觸發(fā)KVO屯曹?
手動調(diào)用willChangeValueForKey:和didChangeValueForKey:
直接修改成員變量會觸發(fā)KVO么?
不會觸發(fā)KVO惊畏,因為直接修改成員變量并沒有走set方法恶耽。
通過KVC修改屬性會觸發(fā)KVO么?
會颜启,KVC內(nèi)部在修改成員變量的同時是會主動調(diào)用KVO的偷俭。
8. block的分類缰盏,__block的作用口猜,block循環(huán)引用產(chǎn)生的原因及解決辦法济炎,block捕獲變量的流程是什么须尚?
- blcok有六種,三種系統(tǒng)(源碼中有密幔,不常用胯甩,此處不做細說)蜡豹,三種常用如下:
- 全局blcok:當(dāng)生成的block是獨立的镜廉,不引用外部變量或者作為參數(shù)參與其他函數(shù)娇唯,則處于全局區(qū),為全局block梗摇。
- 堆block:當(dāng)block 引用外部變量伶授,此時block 會從全局區(qū)移動到堆區(qū)
- 棧block:當(dāng)block 被copy 前糜烹,會處于棧區(qū)疮蹦,當(dāng)棧block賦值給block變量后愕乎,棧block就會被拷貝到堆上壁公,成為堆block贮尖。
- 在 MRC下:只要沒有訪問外部變量湿硝,就是全局block关斜。訪問了外部變量,就是棧block垛膝。顯示地調(diào)用[block copy]就是堆block吼拥。
- 在 ARC下:只要沒有訪問外部變量凿可,就是全局block枯跑。如果訪問了外部變量,那么在訪問外部變量之前存儲在棧區(qū)粗卜,訪問外部變量之后存儲在堆區(qū)续扔。
- __block的作用:
__block
在作用域內(nèi)部生成了變量的指針测砂,通過改變指針指向的地址,來改變原變量呜投。
- __block修改外面變量的原理:為對應(yīng)的__block變量生成了一個結(jié)構(gòu)體仑荐,該結(jié)構(gòu)體中保存了外界變量的指針和值粘招,傳遞了一個指針給block函數(shù)調(diào)用洒扎。從而可以實現(xiàn)修改外面變量袍冷。
- block循環(huán)引用問題:當(dāng)一個類的對象持有block胡诗,block里面又引用了這個對象,那么就是一個循環(huán)引用的關(guān)系骇陈。
防止循環(huán)引用的三種方式:
- __weak打破強引用關(guān)系
- 中介者模式你雌,傳入臨時量VC匪蝙,在block執(zhí)行完成后手動置為nil
- block傳參防止循環(huán)引用
block捕獲變量的流程:除了靜態(tài)變量和全局變量以外逛球,都是block 在內(nèi)部自動生成一個新的變量,用來接收外部變量幸海。
9. 說一下對GCD的了解物独,它有哪些方法挡篓,分別是做什么用的官研?
- GCD 可用于多核并行運算
- GCD 會自動利用更多的 CPU 內(nèi)核(比如雙核戏羽、四核)
- GCD 會自動管理線程的生命周期 (創(chuàng)建線程始花、調(diào)度任務(wù)酷宵、銷毀線程)
- 程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù)浮创,不需要編寫任何線程管理代碼
GCD方法及使用
- GCD信號量: dispatch_semaphore
// 創(chuàng)建一個Semaphore并初始化信號的總量
dispatch_semaphore_create
// 發(fā)送一個信號斩披,讓信號量+1
dispatch_semaphore_signal
// 可使總信號量減1垦沉,信號總量小于0時會一直等待(阻塞當(dāng)前線程)厕倍,否則就可以正常執(zhí)行
dispatch_semaphore_waite
- GCD隊列組:dispatch_group
// 創(chuàng)建隊列組
dispatch_group_t * group = dispatch_group_create();
// 把任務(wù)放在隊列組
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//任務(wù)一....
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
// 任務(wù)二....
});
// 執(zhí)行完前兩個異步任務(wù)后的兩種操作:
dispatch_group_notify(group,dispatch_get_main_queue(),^{
//任務(wù)三
});
// 當(dāng)前兩個異步任務(wù)完成后这溅,把任務(wù)三添加到group中
// 此函數(shù)會阻塞當(dāng)前線程悲靴,等前兩個異步任務(wù)完成后才可解除阻塞
dispatch_group_wait (group,DISPATCH_TIME_FOREVER);
- GCD一次性代碼(只執(zhí)行一次癞尚,單例):dispatch_once
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只執(zhí)行 1 次的代碼(這里面默認是線程安全的)
});
- GCD延時執(zhí)行方法:dispatch_after
- GCD柵欄方法:dispatch_barrier_async
- 柵欄函數(shù)其實是作為堵塞隊列而存在的(同步函數(shù)是作為堵塞線程存在的)
- 堵塞隊列意思就是在柵欄函數(shù)之前的任務(wù)要全部執(zhí)行完才開始執(zhí)行柵欄函數(shù)
- 并且柵欄函數(shù)執(zhí)行完后才執(zhí)行柵欄函數(shù)之后的任務(wù)
- 但是柵欄函數(shù)不能用于全局并發(fā)隊列浇揩,因為全局并發(fā)隊列系統(tǒng)也在用胳徽,假如用柵欄函數(shù)將全局并發(fā)隊列堵塞住了膜廊,會導(dǎo)致系統(tǒng)運行不正常而導(dǎo)致崩潰
// dispatch_barrier_async 方法會等待前邊追加到并發(fā)隊列中的任務(wù)全部執(zhí)行完畢后,再將指定的任務(wù)追加到該barrier異步隊列中匙瘪。等該barrier任務(wù)完成后丹喻,異步隊列才恢復(fù)為正常執(zhí)行后邊的任務(wù)碍论。
- (void)barrier {
dispatch_queue_t queue = dispatch_queue_create("dezi.testQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 追加任務(wù) 1
[NSThread sleepForTimeInterval:3]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當(dāng)前線程
});
dispatch_async(queue, ^{
// 追加任務(wù) 2
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當(dāng)前線程
});
dispatch_barrier_async(queue, ^{
// 追加任務(wù) barrier柵欄函數(shù)
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"barrier---%@",[NSThread currentThread]);// 打印當(dāng)前線程
});
dispatch_async(queue, ^{
// 追加任務(wù) 3
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當(dāng)前線程
});
dispatch_async(queue, ^{
// 追加任務(wù) 4
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"4---%@",[NSThread currentThread]); // 打印當(dāng)前線程
});
}
// 打印
test[4592:1385282] 2---<NSThread: 0x600002ce7100>{number = 6, name = (null)}
test[4592:1385288] 1---<NSThread: 0x600002cd45c0>{number = 5, name = (null)}
test[4592:1385288] barrier---<NSThread: 0x600002cd45c0>{number = 5, name = (null)}
test[4592:1385282] 3---<NSThread: 0x600002ce7100>{number = 6, name = (null)}
test[4592:1385288] 4---<NSThread: 0x600002cd45c0>{number = 5, name = (null)}
10. 對二叉樹是否了解?
由n (n>=0)個結(jié)點所構(gòu)成的集合坐搔,它可以為空樹(n=0)概行。
對于?空樹T:有且僅有?個稱之為根結(jié)點,除了根結(jié)點以外的其余結(jié)點分為2個互不相交的?集T1禽炬、T2腹尖。分別稱為T的左?樹和右?樹却紧,且T1和T2本身 都是?叉樹晓殊。
詳細介紹可參考這篇文章:二叉樹巫俺。
二面
1. ARC和MRC的區(qū)別介汹,iOS是如何管理引用計數(shù)的,什么情況下引用計數(shù)加1窗价,什么情況下引用計數(shù)減1撼港?
內(nèi)存管理相關(guān)可參考 iOS內(nèi)存管理
MRC:開發(fā)者手動地進行retain和release操作帝牡,對每個對象的retainCount進行+1靶溜、-1操作罩息,當(dāng)retainCount為0時挎狸,系統(tǒng)會自動釋放對象內(nèi)存锨匆。
ARC:開發(fā)者通過聲明對象的屬性為strong,weak茅主,assign來管理對象的引用計數(shù)诀姚,系統(tǒng)會自動對所修飾變量的引用計數(shù)進行自增自減操作赫段,同樣地糯笙,retainCount為0時,系統(tǒng)會釋放對象內(nèi)存豺憔。
alloc時候retainCount默認加1恭应。
2. 在MRC下執(zhí)行[object autorelease]會發(fā)生什么昼榛,autorelease是如何實現(xiàn)的褒纲?自動釋放池中的autorelease對象是什么時候銷毀的?
autorelease
是iOS開發(fā)的一種內(nèi)存管理機制衫嵌,調(diào)用autorelease
會將該對象添加進自動釋放池中楔绞,它會在一個恰當(dāng)?shù)臅r刻自動給對象調(diào)用release
酒朵,所以autorelease
相當(dāng)于延遲了對象的釋放。结耀。
- 對象調(diào)用
autorelease
時图甜,會將對象壓棧到AutoreleasePoolPage
中黑毅。- 進作用域空間調(diào)用
objc_autoreleasePoolPush
壓棧,出作用域空間調(diào)用objc_autoreleasePoolPop
向棧中對象發(fā)送release
釋放來出棧@autoreleasepool
與線程關(guān)聯(lián)枕面,一個@autoreleasepool
對應(yīng)一個線程@autoreleasepool
嵌套只會創(chuàng)建一個page潮秘,但會有兩個哨兵(POOL_BOUNDARY
)
AppKit 和 UIKit 框架在事件循環(huán)(RunLoop)的每次循環(huán)開始時唇跨,在主線程創(chuàng)建一個自動釋放池买猖,并在每次循環(huán)結(jié)束時銷毀它玉控,在銷毀時釋放自動釋放池中的所有autorelease對象高诺。
3. CoreAnimation是如何繪制圖像的虱而,動畫過程中的frame能否獲取到开泽?CALayer與UIView的關(guān)系穆律?
圖像繪制是按圖層數(shù)一層一層繪制的峦耘。CoreAnimation在
Runloop
中注冊一個Observer
監(jiān)聽視圖變化的事件辅髓,有需要時會進行更新少梁。
動畫過程中的
frame
是無法獲取到的猎莲,只能知道起始和終點位置信息著洼。
CALayer與UIView的關(guān)系
- UIView本身不具備顯示的功能身笤,CALayer才有顯示功能液荸。當(dāng)UIView需要顯示到屏幕上時脱篙,會調(diào)用
drawRect:
方法進行繪圖,并且會將所有內(nèi)容繪制在自己的圖層上文搂,繪圖完畢后煤蹭, 系統(tǒng)會將圖層拷貝到屏幕上取视,于是就完成了UIView的顯示作谭。- 對比CALayer折欠,UIView多了一個事件處理的功能怨酝。也就是說那先,CALayer不能處理用戶的觸摸事件售淡,而UIView可以。
- 如果顯示出來的東西需要跟用戶進行交互的話揍堕,用UIView衩茸;如果不需要跟用戶進行交互,用UIView或者CALayer都可以幔烛。當(dāng)然饿悬,CALayer的性能會高一些狡恬,因為它少了事件處理的功能弟劲,更加輕量級夫啊。
4. 談一下Runloop的了解
詳細分析可參考 Runloop
- Runloop實際上就是一個do...while循環(huán)撇眯,有任務(wù)時執(zhí)行熊榛,無任務(wù)時休眠玄坦。
- 每條線程都有唯一的一個與之對應(yīng)的RunLoop對象
RunLoop保存在一個全局的Dictionary里,線程作為key豺总,RunLoop作為value喻喳。- 主線程的RunLoop會在App運行的時自動運行困曙,子線程需要手動獲取運行,第一次獲取時鳄哭,才會去創(chuàng)建纲熏。
Runloop的作用:保持程序的持續(xù)運行,處理APP中的各種事件(觸摸飘痛、定時器宣脉、performSelector)剔氏,節(jié)省cpu資源羊苟、提供程序的性能感憾,該做事就做事阻桅,該休息就休息嫂沉。
Runloop Mode的主要Mode
- NSDefaultRunLoopMode:默認的運行模式,除了NSConnection對象的事件杏糙。
- NSRunLoopCommonModes:是一組常用的模式集合宏侍,將一個input source關(guān)聯(lián)到這個模式集合上负芋,等于將input source關(guān)聯(lián)到這個模式集合中的所有模式上。在iOS系統(tǒng)中NSRunLoopCommonModes包含NSDefaultRunLoopMode锨天、NSTaskDeathCheckMode病袄、UITrackingRunLoopMode赘阀。
- UITrackingRunLoopMode:用于跟蹤觸摸事件觸發(fā)的模式(例如UIScrollView上下滾動)幅慌, 主線程當(dāng)觸摸事件觸發(fā)會設(shè)置為這個模式轰豆,可以用來在控件事件觸發(fā)過程中設(shè)置Timer酸休。
- GSEventReceiveRunLoopMode:用于接受系統(tǒng)事件,屬于內(nèi)部的RunLoop模式渗饮。
- 自定義Mode:可以設(shè)置自定義的運行模式Mode互站,你也可以用CFRunLoopAddCommonMode添加到NSRUnLoopCommonModes中。
Run Loop 運行時只能以一種固定的模式運行谤饭,如果我們需要它切換模式亡容,只有停掉它冤今,再重新開其它屋谭。
運行時它只會監(jiān)控這個模式下添加的Timer Source和Input Source桐磁,如果這個模式下沒有相應(yīng)的事件源我擂,RunLoop的運行也會立刻返回的校摩。
5. OC如何實現(xiàn)多繼承衙吩?
- 消息的轉(zhuǎn)發(fā)
- delegate和protocol
- 分類Category
6. 對設(shè)計模式有什么了解车猬,講一下其中一種是如何是用的?
MVC:通過數(shù)據(jù)模型尺锚,控制器邏輯珠闰,視圖展示將應(yīng)用程序進行邏輯劃分。
MVVM:它其實是一個MVC的增強版瘫辩,并將邏輯從Controller移出放到一個新的對象里伏嗜,即View Model在iOS上使用MVVM的動機,就是讓它能減少ViewController的復(fù)雜性并使得表示邏輯更易于測試伐厌。
單例:確保程序運行期某個類承绸,只有一份實例,用于進行資源共享控制挣轨。
確保使用者只能通過getInstance方法才能獲取军熏,保證單例類的唯一性。重寫allocWithZone方法,保證即使用戶用alloc方法直接創(chuàng)建單例類的實例,返回的也只是此單例類的唯一靜態(tài)變量或衡。
Notification:一般為model層對,controller和view進行的通知方式,不關(guān)心誰去接收祖搓,只負責(zé)發(fā)布信息。
通知
代理:當(dāng)一個類的某些功能需要由別的類來實現(xiàn),但是又不確定具體是哪個類實現(xiàn)羔杨。
7. 有沒有哪個開源庫讓你用得很舒服曙寡,講一下讓你舒服的地方忌愚。
** MJExtension+FMDB+JKDBModel**
SDWebImage 的圖片加載過程:
- 查看緩存
- 緩存命中
- 返回圖片
- 更新 UIImageView
- 緩存未命中
- 異步下載圖片
- 加入緩存
- 更新 UIImageView
8. 一張100*100 RGBA的png圖像,解壓之后占多大內(nèi)存空間
套用公式,RGBA是32位
100*100*32/8 = 40000(字節(jié))
40000/1024 = 39KB
9. 給定一個數(shù)組arr亚侠,判斷數(shù)組arr中是否所有的數(shù)字都只出現(xiàn)過一次铜幽。
我的想法是,取第一個數(shù)從下一位開始遍歷,有return true护蝶,沒有則取第二位從第三位開始遍歷帽馋,以此類推,遍歷到倒數(shù)第二位检诗。
10. Swift和OC的區(qū)別,優(yōu)缺點鉴象?
- Swift容易閱讀淆游,語法和文件結(jié)構(gòu)簡易化吮炕。
- Swift更易于維護俱笛,文件分離后結(jié)構(gòu)更清晰。
- Swift更加安全,它是類型安全的語言。
- Swift代碼更少族壳,簡潔的語法坏平,可以省去大量冗余代碼
- Swift速度更快孽亲,運算性能更高
但是版本不夠穩(wěn)定孵延,更新迭代還會有
11. Category(類別/分類)和Extension(擴展)的區(qū)別:
Category
- 是運行期決議的
- 可以在不修改原來類的基礎(chǔ)上玷犹,為一個類擴展方法。如:給系統(tǒng)自帶的類擴展方法鹅经。
- 分類不能添加實例變量劫拢,但類擴展可以
- 原因:因為在運行期距糖,對象的內(nèi)存布局已經(jīng)確定黎休,如果添加實例變量會破壞類的內(nèi)部布局歹啼,這對編譯性語言是災(zāi)難性的。
Extension
- 在編譯期決議炕倘,是類的一部分
- 伴隨著類的產(chǎn)生而產(chǎn)生逝撬,也隨著類的消失而消失拦键。
- 類擴展即可以聲明成員變量又可以聲明方法
- Extension一般用來隱藏類的私有消息,你必須有一個類的源碼才能添加一個類的Extension唯袄,所以對于系統(tǒng)一些類,如NSString且叁,就無法添加類擴展
12. 為什么離職,有什么職業(yè)規(guī)劃络它。
個人發(fā)揮掠廓。