續(xù)寫iOS 面試題及答案20道(一)
21.OC中什么是ARC院尔?Objective-C的內(nèi)存管理機(jī)制是什么?
ARC即Automatic Refrence Counting,它是Objective-C的內(nèi)存管理機(jī)制。就是在代碼中自動(dòng)加入了retain/release,原先需要手動(dòng)添加用于管理內(nèi)存的引用計(jì)數(shù)的代碼可以由編譯器自動(dòng)完成纷妆。
ARC的使用是為了解決對(duì)象retain和release匹配的問題。以前因手動(dòng)管理而造成內(nèi)存泄漏或者重復(fù)釋放的問題將不復(fù)存在晴弃。
以前需要手動(dòng)去釋放內(nèi)存掩幢,retain了以后必須release釋放內(nèi)存。alloc new retain都需要release上鞠,這種操作為MRC(Manual Reference Counting).
ARC與Garbage Collection的區(qū)別在于际邻, Garbage Collection在運(yùn)行時(shí)管理內(nèi)存,可以解決retain cycle芍阎,而ARC在編譯時(shí)管理內(nèi)存世曾。
22.OC中什么情況下會(huì)出現(xiàn)循環(huán)引用?
循環(huán)引用就是兩個(gè)或以上對(duì)象互相強(qiáng)引用谴咸,當(dāng)這些對(duì)象釋放的時(shí)候轮听,導(dǎo)致互相釋放不掉骗露,這種情況就是循環(huán)引用,這也是內(nèi)存泄漏的一種情況血巍。 在OC中解決方法就是在一個(gè)對(duì)象的強(qiáng)引用Strong(強(qiáng)引用) 改成weak(弱引用)萧锉。
循環(huán)引用其實(shí)在Xcode工具中是可以檢測(cè)到的。比如:
Xcode->Debug Memory Graph檢查述寡,就是在一個(gè)對(duì)象中打一個(gè)斷點(diǎn)柿隙,點(diǎn)擊輸出控制器上面的三個(gè)點(diǎn)用線串起來的按鈕來查看類中的引用圖,根據(jù)該不該釋放的問題來查找是否循環(huán)引用了鲫凶。
在Xcode左上角禀崖,感嘆號(hào)按鈕由一個(gè)runtime的選項(xiàng),一般如果有內(nèi)存泄漏會(huì)直接在里面暴漏出來
Xcode->Product->analyze 來發(fā)現(xiàn)內(nèi)存泄漏問題螟炫。
23.說明比較OC中關(guān)鍵字:strong波附、weak、assign和Copy
參數(shù) | 詳解 |
---|---|
strong | 表示指向并擁有該對(duì)象昼钻,其修飾的對(duì)象引用計(jì)數(shù)+1叶雹,該對(duì)象只要引用計(jì)數(shù)不為0,就不會(huì)被銷毀换吧。當(dāng)然,強(qiáng)行將其設(shè)為nil也可以銷毀它钥星。不需要手動(dòng)釋放內(nèi)存 |
weak | 類似assign沾瓦,一般情況下修飾對(duì)象,而assign一般修飾值類型谦炒,比assign多了一點(diǎn)就是對(duì)象被銷毀的時(shí)候贯莺,weak引用會(huì)自動(dòng)設(shè)置為nil,防止野指針的發(fā)生宁改,修飾的對(duì)象引用計(jì)數(shù)不會(huì)改變缕探。在一個(gè)強(qiáng)引用引用該對(duì)象時(shí),如果這個(gè)強(qiáng)飲用被釋放掉了还蹲,那么同樣爹耗,這個(gè)對(duì)象也會(huì)被釋放。 |
assign | 直接賦值谜喊,默認(rèn)值潭兽,主要是修飾一些基本數(shù)據(jù)類型,值類型斗遏,比如說NSInteger山卦、CGFloat,這些數(shù)值主要存在于棧中诵次。 |
copy | copy與strong類似账蓉,不同之處是枚碗,strong賦值的話,會(huì)是指針的復(fù)制铸本,并且內(nèi)容是同一塊兒地址肮雨,而copy不同,每次賦值或復(fù)制的時(shí)候都會(huì)復(fù)制一份新的對(duì)象归敬,指針指向不同的地址酷含,copy一般用在修飾有對(duì)應(yīng)可變類型的不可變對(duì)象上,如NSString,NSArray和NSDictionary汪茧。 |
在OC中基本的數(shù)據(jù)類型的屬性變量的關(guān)鍵字是(atomic椅亚、readwrite、assign)舱污;普通屬性的默認(rèn)關(guān)鍵字是(atomic呀舔、readwrite、Strong)
24.說明比較關(guān)鍵字:atomic和nonatomic
參數(shù) | 詳情 |
---|---|
atomic | 作用是系統(tǒng)生成的setter/getter方法會(huì)保證get扩灯、set操作的完整性媚赖,不受其他線程影響,如果A線程的getter方法運(yùn)行到一半的時(shí)候珠插,線程B調(diào)用了setter方法惧磺,那么線程A還是能夠得到一個(gè)完好無損的對(duì)象,所以速度比較慢捻撑,atomic比nonatomic安全磨隘,但是并不是絕對(duì)的安全,比方說多個(gè)線程同時(shí)調(diào)用set和get方法顾患,會(huì)導(dǎo)致獲得的對(duì)象不一樣番捂,如果想要線程絕對(duì)的安全,就要用@synchronized 代碼塊江解。 |
nonatomic | 這個(gè)修飾的對(duì)象并不會(huì)保證setter/getter方法的完整性设预,但是速度比atomic快,當(dāng)多線程訪問的時(shí)候有可能得到的是未初始化的對(duì)象犁河,當(dāng)然也不是線程安全的鳖枕。 |
25.atomic是百分之百線程安全的嗎?
atomic不是百分之百線程安全的桨螺,只是保證多線程的情況下耕魄,getter、setter方法調(diào)用的完整性彭谁,在多線程訪問的情況下吸奴,能夠有效完整的調(diào)用完setter、getter方法。
但是在多線程并發(fā)的情況下则奥,得到的結(jié)果不能夠保證是統(tǒng)一的考润,比如說線程A在調(diào)用屬性M的setter方法并且進(jìn)行到了一半的時(shí)候,線程B調(diào)用了getter方法想要獲取到M的內(nèi)容读处,那么線程B拿到的是線程A賦值之前的內(nèi)容糊治,如果需求是要獲取到線程A賦完值以后的內(nèi)容,那么這就是線程不安全的實(shí)例罚舱。
26.Runloop和線程的關(guān)系井辜?
runloop是每一個(gè)線程一直運(yùn)行的一個(gè)對(duì)象,它主要用來負(fù)責(zé)響應(yīng)需要處理的各種事件和消息管闷。每一個(gè)線程都有且僅有一個(gè)runloop與其對(duì)應(yīng)粥脚。沒有線程,就沒有runloop包个。
在所有的線程中刷允,只有主線程的runloop是默認(rèn)啟動(dòng)的。main函數(shù)會(huì)設(shè)置一個(gè)NSRunLoop對(duì)象碧囊。而其他線程的runloop默認(rèn)是沒有啟動(dòng)的树灶。可以通過[NSRunLoop currentRunLoop]獲取當(dāng)前的runloop糯而,調(diào)用run啟動(dòng)天通。
27.說明并比較關(guān)鍵字:__weak和__block。
-
__weak與weak基本上是一樣的熄驼,前者修飾變量(variable)像寒,后者修飾屬性(perproty)。
__weak主要用于防止在block中的循環(huán)引用谜洽,
__block
也用于修飾變量。它是引用修飾吴叶,所以其修飾的值是動(dòng)態(tài)變化的阐虚。就是可以被重新賦值。__block
用于修飾某些block內(nèi)部將要修改的外部的變量蚌卤。
__weak
和__block
的使用場(chǎng)景幾乎與block息息相關(guān)实束。而所謂block,就是Objective-C對(duì)于閉包的實(shí)現(xiàn)逊彭。閉包就是沒有名字的函數(shù)咸灿,或者可以理解為指向函數(shù)的指針。
使用注意侮叮,如果在block中去修改外部的變量(除靜態(tài)避矢、全局),需要在block外部聲明
__weak
重新修飾,然后在block中在用__block
在去修飾__weak
修飾的變量审胸。__weak
修飾是為了告訴編譯器亥宿,重新修飾的變量是一個(gè)不使用引用計(jì)數(shù)的弱引用,
而在block中使用__block
是為了告訴編譯器砂沛,我需要在block使用這個(gè)變量不管是外面的變量是否被釋放掉烫扼,我的block中的這個(gè)變量要在整個(gè)block函數(shù)中應(yīng)該全程都是被保留的。如:
__weak typeof(self)weakself = self;
self.Copyblock = ^{
__block typeof(weakself)blockself = weakself;
[blockself.array addObject:[UserModel new]];
};
self.Copyblock();
28.什么是block碍庵?它和代理的區(qū)別是什么映企?
block是一個(gè)回調(diào)的方式,本質(zhì)上也是一個(gè)OC對(duì)象静浴,一個(gè)函數(shù)方法對(duì)象堰氓。
block分為三種: 靜態(tài)block、棧block马绝、堆block豆赏。
block和代理的區(qū)別:
block
集中代碼塊,而delegate
則是分散代碼塊富稻。block
可讀性更好掷邦、使用簡(jiǎn)單,而delegate
則需要聲明協(xié)議椭赋、聲明代理屬性抚岗、遵守協(xié)議、實(shí)現(xiàn)協(xié)議的方法哪怔。而block
只需要聲明屬性宣蔚、實(shí)現(xiàn)就可以。block
是一個(gè)輕量級(jí)的回調(diào)认境,可以直接上下文胚委,因?yàn)榇a內(nèi)聯(lián)運(yùn)行效率更高,block就是一個(gè)對(duì)象叉信,實(shí)現(xiàn)了匿名函數(shù)的功能亩冬。所以把block
當(dāng)作一個(gè)成員變量、屬性硼身、參數(shù)使用硅急,使用起來非常的靈活。就想AFN的請(qǐng)求數(shù)據(jù)佳遂,GCD的多線程营袜,而delegate
就沒有這么靈活。block
適用于輕便丑罪、簡(jiǎn)單的回掉荚板,比如一些簡(jiǎn)單回調(diào)網(wǎng)絡(luò)數(shù)據(jù)凤壁,相對(duì)來說借口比較少的回調(diào)等, 如果是一些復(fù)雜的函數(shù)回掉啸驯,并且接口過多客扎,那么使用block就會(huì)顯得不利于維護(hù)、耦合性太大罚斗,而代理則完全相反徙鱼,接口回調(diào)少的時(shí)候使用起來比較麻煩,但是一旦接口回調(diào)多的時(shí)候针姿,會(huì)顯得更加清晰明朗袱吆。block
的運(yùn)行成本高侍瑟,block
出棧的時(shí)候需要將數(shù)據(jù)從棧內(nèi)存拷貝到堆內(nèi)存夷蚊,如是對(duì)象是加計(jì)數(shù),那么使用完或者block
置為nil后才能被消除耕腾;delegate
只是保存了一個(gè)對(duì)象指針榕暇,直接回調(diào)蓬衡,并沒有額外消耗。block
容易產(chǎn)生循環(huán)引用彤枢,當(dāng)然(delegate
需要weak
修飾狰晚,不然也是有循環(huán)引用),因?yàn)闉榱?code>block不被系統(tǒng)回收缴啡,所以我們都用copy關(guān)鍵字修飾壁晒,實(shí)行強(qiáng)引用,block
對(duì)捕獲的變量也都是強(qiáng)引用业栅,所以就會(huì)造成循環(huán)引用秒咐。
如果使用? 1)簡(jiǎn)單的來講優(yōu)先使用block 2) 如果回調(diào)的狀態(tài)多碘裕,超過2個(gè)以上就是用代理 3)如果回調(diào)過于頻繁携取,還是使用代理。 按需使用
29.屬性中copy和Strong的面試問題帮孔?
@property(nonatomic,strong)NSString * title;
@property(nonatomic,assign)int num;
第一個(gè)屬性:title:
- NSString這個(gè)類型有可變不可變的類型雷滋,NSMutableString這個(gè)類型,并且是NSString的子類你弦。那么使用strong的話容易被外界所修改惊豺。比方說:
類A中定義了title屬性(nonatomic,strong)燎孟,類A中有個(gè)變量(NSMutableString)的變量Mutabletitle
//mutableString這個(gè)參數(shù)是類A的一個(gè)變量類型是NSMutableString
NSMutableString* mutableString = [[NSMutableString alloc]initWithString:@"mutablestring"];
UserModel *user = [[UserModel alloc]init];
//首先將字符串賦值
user.title = @"title";
user.title = mutableString; //這時(shí)候title==mutableString==@"mutablestring"
//修改mutableString的值
[mutableString appendString:@"111"];
//得到的結(jié)果是user.title == mutableString == @"mutablestring111"
NSLog(@"title=%@--%p mutableString=%@--%p",user.title,user.title,mutableString,mutableString);
如果在開發(fā)中禽作,我們只是修改mutableString的值而并不想修改user.title的值,那么這樣做就是錯(cuò)誤的揩页。
分析:由于strong修飾的屬性是強(qiáng)引用旷偿,user.title = mutableString 這個(gè)意思就是直接指針復(fù)制,這兩個(gè)變量所擁有的內(nèi)存地址是一樣的,當(dāng)一個(gè)變量修改另外的變量也會(huì)跟著修改萍程。
第二個(gè)屬性num幢妄,這個(gè)屬性不應(yīng)該用int來修飾,int是代表32位的整型數(shù)據(jù)茫负,而在iOS中有個(gè)整型NSinteger這個(gè)屬性蕉鸳,表示在32位系統(tǒng)中是32位的整型,在64位系統(tǒng)中會(huì)是64位整型數(shù)據(jù)忍法, NSinteger更加準(zhǔn)確潮尝。當(dāng)然還有 CGFloat代替float NSUInteger代替unsigned。
改正代碼:
@property(nonatomic,copy)NSString * title;
@property(nonatomic,assign)NSInteger num;
30.閱讀下述代碼饿序,看這個(gè)代碼是否能夠更加優(yōu)化勉失,在架構(gòu)解耦中應(yīng)該怎么做。
typedef enum{
normal = 0;
VIP = 1;
}UserPowerType;
@interface UserModel:NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,strong)UIImage *UserIcon;
@property(nonatomic,assign)UserPowerType Type;
@end
1.首先enum的定義原探,apple官方推薦使用NS_ENUM來定義枚舉類型乱凿,同時(shí)在每個(gè)枚舉的前面需加上枚舉的名稱,也方便swift和OC混編咽弦。
2.UIImage這個(gè)參數(shù)不應(yīng)該出現(xiàn)在UserModel中徒蟆,因?yàn)閁IImage這個(gè)明顯是UIKit中的組建,是放到View 中的內(nèi)容离唬,無論是MVC還是MVVM或者是VIPER后专,Model都應(yīng)該跟View劃清界限。
優(yōu)化后的代碼:
typedef NS_ENUM(NSUInteger, UserPowerType) {
UserPowerTypeNormal,
UserPowerTypeVIP,
};
@interface UserModel:NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,strong)NSData *UserIconData;
@property(nonatomic,assign)UserPowerType Type;
@end
31.閱讀下述代碼從內(nèi)存管理中分析其真正的意義输莺。
NSString *str1 =@"helloworld";
NSString *str2 =@"helloworld";
if(str1 == str2){
NSLog(@"equal");
}else{
NSLog(@"not equal");
}
NSLog(@"str1=%p,str2=%p",str1,str2);
- ==符號(hào)并不是判斷這兩個(gè)值是否相等戚哎,而是判斷這兩個(gè)指針是否指向同一個(gè)對(duì)象,如果要判斷兩個(gè)對(duì)象的值是否相同應(yīng)該用方法
isEqualToString
這個(gè)方法嫂用。 - 那么上述代碼為什么打印出來的結(jié)果是equal吶型凳?因?yàn)樵趇OS的編譯器環(huán)境中,會(huì)優(yōu)化內(nèi)存分配嘱函,當(dāng)兩個(gè)指針指向兩個(gè)值一樣的NSString時(shí)甘畅,兩者會(huì)同時(shí)指向一個(gè)地址。所以代碼打印的結(jié)果是equal往弓。
32.閱讀下述有關(guān)多線程的代碼疏唾,并說明有什么問題?
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
label.text = @"123456";
label.textColor = [UIColor redColor];
[self.view addSubview:label];
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc]init];
[backgroundQueue addOperationWithBlock:^{
[NSThread sleepForTimeInterval:4];
label.text = @"amaze";
}];
這段代碼最大的問題函似,只要跟刷新界面有關(guān)系的內(nèi)容必須在主線程中調(diào)用槐脏。
正確的代碼修正:
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 40)];
label.text = @"123456";
label.textColor = [UIColor redColor];
[self.view addSubview:label];
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc]init];
[backgroundQueue addOperationWithBlock:^{
[NSThread sleepForTimeInterval:4];
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
label.text = @"amaze";
}];
}];
33.以ScheduledTimerWithTimeInterval的方式觸發(fā)的timer,在滑動(dòng)頁面上的列表時(shí)撇寞,timer會(huì)暫停顿天,為什么堂氯?該如何解決?
造成此問題的原因在于滑動(dòng)頁面上的列表時(shí)牌废,當(dāng)前線程的runloop切換了mode的模式咽白,導(dǎo)致timer暫停。
runloop中的mode主要用來指定事件在runloop中的優(yōu)先級(jí)鸟缕,具體有以下幾種:
參數(shù) | 詳情 |
---|---|
default(NSDefaultRunLoopMode) | 默認(rèn)設(shè)置晶框,一般情況下使用 |
Connection(NSConnectionReplyMode) | 用于處理NSConnection相關(guān)事件,開發(fā)者一般用不到 |
Modal(NSModalPanelRunLoopMode) | 用于處理model panels |
Event Tracking(NSEventTrackingRunLoopMode) | 用于處理拖拽和用戶交互的模式 |
Common (NSRunLoopConmmonModes) | 模式合集懂从,默認(rèn)包括Default三妈、modal和EventTracking三大模式,可以處理幾乎所有的事件 |
根據(jù)上面的參數(shù)介紹在看這道問題莫绣,在滑動(dòng)列表時(shí)畴蒲,runloop的mode由原來的Default模式切換到EventTracking模式,timer原來運(yùn)作在Default模式中对室,模式切換了以后自然而然就停止工作了模燥。
解決方法:方法一是將timer加入NSRunloopCommonModes中。方法二是將timer放到另一個(gè)線程中掩宜,然后開啟另一個(gè)線程的runloop蔫骂,這樣可以保證與主線程互不干擾,而現(xiàn)在主線程正在處理頁面滑動(dòng)牺汤。
代碼示例:
方法一:
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
方法二:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(Repeat) userInfo:nil repeats: YES];
[[NSRunLoop currentRunLoop] run];
})
34.Swift VS Objective-C
這么多年的Swift完善辽旋,Apple的兩種語言已經(jīng)從一開始的分道揚(yáng)鑣,到現(xiàn)在已經(jīng)有了天壤之別檐迟。
細(xì)數(shù)兩種語言大的方面不一樣的地方:
- Swift更注重安全性补胚,比如說Swift的可選、不可選類型追迟,溶其? ! 而OC當(dāng)中并沒有這些規(guī)定敦间,如果非要說共同點(diǎn)就是iOS9.0之后出現(xiàn)的關(guān)鍵字 _NonNull(不可以為nil) 瓶逃、_nullable(可以為nil)就算是不遵守這個(gè)也就是給個(gè)警告,主要是為了混編開發(fā)廓块。
- Swfit有面向?qū)ο缶幊滔峋⒚嫦騾f(xié)議編程、函數(shù)式編程带猴,而OC幾乎只有面向?qū)ο蟮木幊獭?/li>
- Swift更加注重值類型的數(shù)據(jù)結(jié)構(gòu)昔汉,而OC遵循了C語言的一套,注重指針和索引浓利。
- Swfit是靜態(tài)語言挤庇,而OC是動(dòng)態(tài)語言。
35.為什么將String贷掖、Array和Dictionary設(shè)計(jì)成值類型嫡秕?
在Swift中這些設(shè)置成值類型,而OC中則是引用類型苹威。具體的分析如下:
- 值類型相比較引用類型來說最大的優(yōu)勢(shì)是可以高效的使用內(nèi)存昆咽,值類型在棧上進(jìn)行操作,而引用類型在堆上面進(jìn)行操作牙甫,棧的操作知識(shí)指針的上下移動(dòng)掷酗,而堆上的操作就需要合并、移位窟哺、重新鏈接泻轰。Swift大幅度減少了堆上的內(nèi)存分配和回收次數(shù),同時(shí)copy-on-write又將值傳遞和復(fù)制的開銷降到了最低且轨。
- 同時(shí)這樣設(shè)計(jì)也是為了線程更加安全浮声,通過Swift的let設(shè)置,使得這些數(shù)據(jù)達(dá)到了真正意義上的不變旋奢,也從根本上解決了多線程中內(nèi)訪問和操作順序問題泳挥。
36.如何用Swift協(xié)議中的部分方法設(shè)計(jì)成可選(optional)
方法一: 用OC的方式實(shí)現(xiàn),在方法前面添加 @objc optional
@objc protocol Myprotocol{
func requiredFunc()
@objc optional func optionalFunc()
}
方法二:用擴(kuò)展來實(shí)現(xiàn)可選方法至朗,擴(kuò)展協(xié)議
protocol Myprotocol{
func requiredFunc()
func optionalFunc()
}
extebsion Myprotocol {
func optionalFunc() {
print("to do")
}
}
Class Myclass: Myprotocol {
func requiredFunc() {
print("only need to implement the required")
}
}
37.判斷下面所述代碼有什么問題屉符?
protocol ProtocolDelegate {
func doSomething()
}
class MyClass {
weak var delegate:ProtocolDelegate?
}
weak var delegate:ProtocolDelegate? //報(bào)錯(cuò)弱引用只能修飾引用類型,而在Swift中協(xié)議是可以被值類型實(shí)現(xiàn)锹引,enum矗钟、struct等,所以需要區(qū)別出來嫌变。
weak關(guān)鍵詞用于ARC環(huán)境下真仲,為引用類型提供引用計(jì)數(shù)這樣的內(nèi)存管理,它是不能夠修飾值類型的初澎。
方法一:
直接在聲明的協(xié)議前面加上 @objc這樣就是告訴編譯器這個(gè)協(xié)議還是OC中的協(xié)議秸应,修飾對(duì)像一個(gè)樣就沒毛病
@objc protocol ProtocolDelegate { //方法一
func doSomething()
}
方法二:
在聲明的協(xié)議后面添加關(guān)鍵字 class 告訴編譯器只能由class來實(shí)現(xiàn),那么就忽略掉了值類型碑宴。
protocol ProtocolDelegate: class { //方法二
func doSomething()
}
38.在Swift和Objective-C的混編中如何在Swift文件中調(diào)用OC方法软啼,在OC文件中調(diào)用Swift方法
Swift調(diào)用OC
Swift調(diào)用OC需要在ProjectName-Bridging-Header.h中添加OC的頭文件,這樣就可以調(diào)用了延柠,一般Swift項(xiàng)目中添加OC文件就有提示自動(dòng)添加僑接文件祸挪。
在OC中調(diào)用Swift代碼,則需要導(dǎo)入Swift生成的頭文件ProjectName-Swift.h
當(dāng)然還有就是在OC中調(diào)用Swift代碼需要在Swift方法屬性前面添加@objc來聲明贞间。
39.比較Swift和OC中初始化方法(init)的不同
在OC中初始化方法無法完全保證屬性變量完成初始化贿条,也沒有對(duì)起最警告處理雹仿,所以在初始化類的時(shí)候,有的屬性是空值(nil)整以,初始化方法和普通方法也并沒有實(shí)際差別胧辽,可以多次調(diào)用。
在Swift中初始化方法必須保證非optional的成員變量得到初始化公黑,同時(shí)新增了
convenience
和required
兩個(gè)修飾初始化方法的關(guān)鍵詞邑商,convenience
是對(duì)初始化方法的補(bǔ)充,但是在內(nèi)部必須調(diào)用同一個(gè)類中的designated初始化方法來完成凡蚜,required
是強(qiáng)制子類重寫父類的初始化方法人断。
40.比較swift跟OC的protocol的異同
相同點(diǎn):
都是作為代理,類似接口
不同點(diǎn):
Swift可以對(duì)接口進(jìn)行抽象朝蜘,配合擴(kuò)展恶迈、泛型、關(guān)聯(lián)類型等可以實(shí)現(xiàn)面向協(xié)議編程谱醇。同時(shí)protocol還可以用于值類型蝉绷,比如enum、struct等