版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
iOS程序員面試分類模擬6簡(jiǎn)答題1.
類別與其他特性(類擴(kuò)展和繼承)有什么區(qū)別?正確答案:類別(Category)與繼承(Inheritance)的區(qū)別如下:
1)子類繼承是進(jìn)行類擴(kuò)展的另一(江南博哥)種常用方法,當(dāng)然基于子類繼承的擴(kuò)展更加自由、正式,既可以新增屬性,也可以新增方法。類別可以在不獲悉、不改變?cè)瓉泶a的情況下往里面添加新的方法,但也只能添加方法,不能添加屬性,屬于功能上的擴(kuò)展。類別擴(kuò)展的優(yōu)點(diǎn)是不需要?jiǎng)?chuàng)建一個(gè)新的類,而是在系統(tǒng)中已有的類上直接擴(kuò)展、覆寫,不需要更改類就可以添加并使用擴(kuò)展方法。
2)相對(duì)于子類繼承擴(kuò)展,類別的另一明顯優(yōu)勢(shì)就是實(shí)現(xiàn)了功能的局部化封裝,擴(kuò)展的功能只會(huì)在本類被引用時(shí)看到。例如,假設(shè)原類為UIButton,現(xiàn)在要使用類別擴(kuò)展一些用于模塊A的方法,那么這些擴(kuò)展方法就可以定義在一個(gè)叫作UIButton+A.h的頭文件中,只有在引用UIButton+A.h的地方,才能看到模塊A添加的那些擴(kuò)展方法,如果不需要模塊A的功能,那么不引用UIButton+A.h頭文件就看不到UIButton的那些擴(kuò)展方法,實(shí)現(xiàn)擴(kuò)展模塊的隔離。
類別與類擴(kuò)展的區(qū)別如下:
類別和類擴(kuò)展的明顯區(qū)別在于,類擴(kuò)展可以添加屬性。另外,類擴(kuò)展添加的方法是必須要實(shí)現(xiàn)的。類擴(kuò)展可以認(rèn)為是一個(gè)私有的匿名的類別,因?yàn)轭悢U(kuò)展定義在.m文件頭部,添加的屬性和方法都沒有暴露在頭文件,所以在不考慮運(yùn)行時(shí)特性的前提下這些擴(kuò)展屬性和方法只能在類內(nèi)部使用,一定程度上可以說是實(shí)現(xiàn)了私有的機(jī)制。
2.
Objective-C中類別特性的作用及其局限性是什么?正確答案:Objective-C中類別特性的作用如下:
1)可以將類的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中(擴(kuò)充新的方法)。
2)可以創(chuàng)建對(duì)私有方法的前向引用。
3)可以向?qū)ο筇砑臃钦絽f(xié)議。
Objective-C中類別特性的局限性如下:
1)類別只能向原類中添加新的方法,且只能添加而不能刪除或修改原方法,不能向原類中添加新的屬性。
2)類別向原類中添加的方法是全局有效的而且優(yōu)先級(jí)最高,如果和原類的方法重名,那么會(huì)無條件覆蓋掉原來的方法,造成難以發(fā)現(xiàn)的潛在危險(xiǎn)。因此,使用類別添加方法一定注意保證是單純的添加新方法,避免覆蓋原來的方法(可以通過添加該類別的方法前綴來防止沖突)。例如,在多人協(xié)作開發(fā)的過程中,如果團(tuán)隊(duì)中有人在其他成員不知情的情況下使用類別將類中的方法覆蓋了,那么這會(huì)使得項(xiàng)目在運(yùn)行時(shí)出現(xiàn)意想不到的問題,并且難以發(fā)現(xiàn)和糾正問題。
3.
類別和類擴(kuò)展如何使用?正確答案:類別和類擴(kuò)展的區(qū)別已經(jīng)討論過了,最明顯的是類別中不可以添加新屬性而類擴(kuò)展中可以添加屬性。類別的使用方法很簡(jiǎn)單,就是新建某個(gè)類的類別擴(kuò)展文件,然后添加新的方法。而類擴(kuò)展并不常用,只是常用在.m文件中的頭部進(jìn)行頭文件的私有屬性變量補(bǔ)充,也就是所謂的類的Continuous區(qū)域,是將不想暴露給外部的一些變量定義在類擴(kuò)展中。
1.創(chuàng)建類別或類擴(kuò)展文件
首先為工程添加新文件,并選擇文件類型為Objective-CFile,如圖所示。
選擇Objective-CFile
然后填寫自定義的擴(kuò)展名,然后選擇文件類型,這里選擇Category或者Extension,最后選擇要擴(kuò)展的已有類,如圖所示。
設(shè)置新建的類別文件
創(chuàng)建之后就可以得到對(duì)應(yīng)的類別文件了,如圖所示。
類別文件
2.添加新的擴(kuò)展方法
這里以擴(kuò)展NSString類的方法為例展示類別擴(kuò)展的具體用法,分別添加一個(gè)類方法和實(shí)例方法,并調(diào)用。
類別頭文件方法聲明:
/*NSString+Category.h*/
#import<Foundation/Foundation.h>
@interfaceNSString(Category){
/*不可以添加實(shí)例變量,編譯器會(huì)直接報(bào)錯(cuò)!*/
}
/*實(shí)例變量被禁止,此處添加屬性變量足無意義的,定義的新屬性,編譯器沒有實(shí)現(xiàn)存取方法,自己也無法手動(dòng)實(shí)現(xiàn)存取方法,因?yàn)闊o法獲取加下畫線的實(shí)例變量,除非利用運(yùn)行時(shí)強(qiáng)行實(shí)現(xiàn)存取方法才可以成功為類別添加屬性,代價(jià)較高*/
//@property(nonatomic,copy)NSString*newStving;
/*擴(kuò)展一個(gè)類方法*/
+(void)categoryClassMethodOtString;
/*擴(kuò)展一個(gè)實(shí)例方法*/
-(void)categoryInstanceMethodOfString;
@end
類別方法的實(shí)現(xiàn)(類別的方法可以不實(shí)現(xiàn),不實(shí)現(xiàn)則不可調(diào)用,否則會(huì)崩潰):
/*NSString+Category.m*/
#import"NSSuing+Category.h"
@implementationNSString(Category)
+(void)categoryClassMethodofString{
NSLog(@"categoryClassMethodOfString");
}
-(void)categoryInstanceMethodOfString{
NSLog(@"categoryInstanceMethodofString");
}
@end
在需要的類中引入類別頭文件NSString+Category.h,然后即可調(diào)用新方法:
#import"NSString+Category.h"
/*1.調(diào)用類別擴(kuò)展的類方法*/
[NSStringcategoryClassMethodOfString];
/*2.調(diào)用類別擴(kuò)展的實(shí)例方法*/
NSString*string=[NSStringstringWithFormat:@""];
[stringcategoryInstanceMethodOfString];
3.類擴(kuò)展的一般用法
類擴(kuò)展即類的.m文件中@implementation之前開始的部分,所謂的類的continuous區(qū)域。
@interfaceclassname()
//...
@end
類擴(kuò)展的作用本來是用于私有方法的前向聲明,但最新編譯器無須聲明也有相同的效果,因此私有方法可在.m文件中任意位置直接寫實(shí)現(xiàn)而無須在此處進(jìn)行前向聲明。如果在此處聲明方法,那么一定要在后面進(jìn)行實(shí)現(xiàn),否則編譯器會(huì)給出警告?,F(xiàn)在類擴(kuò)展區(qū)域的作用主要是快速定義類的私有屬性,即將暴露給外部的屬性變量定義在頭文件中,而不想暴露給外部的屬性則直接定義在類擴(kuò)展區(qū)域。
注意這里提到的私有屬性和私有方法并不是絕對(duì)私有的,Objective-C中沒有絕對(duì)的私有方法和私有變量,因?yàn)榧词顾鼈冸[藏在.m實(shí)現(xiàn)文件里不暴露在頭文件中,開發(fā)者仍然可以利用runtime運(yùn)行時(shí)機(jī)制對(duì)其暴力訪問,只是一般情況下可以達(dá)到私有化的效果。
/*類擴(kuò)展區(qū)域*/
@interfaceViewController()
/*類擴(kuò)展屬性(默認(rèn)為private,類外部不可訪問)*/
@property(nonatomic,copy)NSString*extensionVariable;
/*類擴(kuò)展方法聲明,可省略,要在立刻在后面進(jìn)行函數(shù)實(shí)現(xiàn)*/
-(void)extensionInstanceMethod;
+(void)extensionClassMethod;
@end
類擴(kuò)展區(qū)域如圖中加框部分。
類擴(kuò)展區(qū)域
4.
為什么類別只能添加擴(kuò)展方法而不能添加屬性變量?正確答案:這個(gè)問法有點(diǎn)疑惑性,實(shí)際問的是為什么向類別添加屬性會(huì)失敗。蘋果公司并不是故意將類別設(shè)計(jì)成不允許開發(fā)者在里面添加屬性,如果是有意,那么可能從設(shè)計(jì)上考慮保持類別特性的單純,專門用來擴(kuò)展功能,和繼承的角色區(qū)別開,防止類別污染被擴(kuò)展的類。
在類別中擴(kuò)展屬性不能成功的原因是無法在類別中取得屬性的加下畫線的實(shí)例變量名,導(dǎo)致無法手動(dòng)實(shí)現(xiàn)實(shí)例變量的存取方法。在類別中定義了屬性后,屬性其實(shí)也成功添加到了類的屬性列表中,但編譯器只為其聲明了存取方法,沒有實(shí)現(xiàn),同時(shí)又沒有合成加下畫線的實(shí)例變量名,導(dǎo)致無法訪問實(shí)例變量也無法自己手動(dòng)實(shí)現(xiàn)其存取方法,對(duì)于一個(gè)不能訪問的屬性,則失去了其存在的意義。
如果使用運(yùn)行時(shí)的機(jī)制,那么開發(fā)者其實(shí)可以強(qiáng)行實(shí)現(xiàn)類別中屬性的存取方法,實(shí)現(xiàn)在類別中擴(kuò)展屬性。這里在運(yùn)行時(shí),實(shí)現(xiàn)為NSString類擴(kuò)展一個(gè)叫作newString的屬性。示例代碼如下:
/*NSString+Category.h*/
#import<Foundation/Foundation.h>
@interfaceNSString(Category)
/*在類別中擴(kuò)展屬性*/
@property(nonatomic,copy)NSString*newString;
@end
/*NSString+Category.m*/
#import"NSString+CategOry.h"
#import<o(jì)bjc/runtime.h>
@implementationNSString(Category)
*運(yùn)行時(shí)強(qiáng)行實(shí)現(xiàn)newString的getter和setter*/
-(NSString*)newString{
returnobjc_getAssociatedObject(self,@"newString");
}
-(void)setNewString:(NSString*)newString{
objc_setAssociatedObject(self,@"newString",newString,OBJC_ASSOCIATION_COPY);
}
@end
/*main.m*/
#import<Foundation/Foundation.h>
#import"NSString+Category.h"
intmain(intargc,constchar*argv[]){
NSString*string;
/*調(diào)用newString的setter方法*/
string.newString=@"newString";
/*調(diào)用newString的getter方法*/
NSLog(@"%@",string.newString);
return():
}
5.
MethodSwizzling的應(yīng)用場(chǎng)景有哪些?正確答案:MethodSwizzling主要用于在運(yùn)行時(shí)對(duì)編譯器編譯好的方法再次進(jìn)行編輯,應(yīng)用場(chǎng)景主要有以下4種。
1.替換類中某兩個(gè)類方法或?qū)嵗椒ǖ膶?shí)現(xiàn)
替換函數(shù):method_exchangeImplementations(method1,method2)。
這里隨便定義一個(gè)Test類,類中定義兩個(gè)實(shí)例方法和類方法并在.m文件中實(shí)現(xiàn),在運(yùn)行時(shí)將兩個(gè)實(shí)例方法的實(shí)現(xiàn)對(duì)調(diào),以及將兩個(gè)類方法的實(shí)現(xiàn)對(duì)調(diào)。注意運(yùn)行時(shí)代碼寫在類的load方法內(nèi),該方法只會(huì)在該類第一次加載時(shí)調(diào)用一次,且編寫運(yùn)行時(shí)代碼的地方需要引入運(yùn)行時(shí)頭文件:
#import<o(jì)bjc/runtime.h>
Test類定義:
/*Test.h*/
#import<Foundation/Foundation.h>
@interfaceTest:NSObject
/*定義兩個(gè)公有實(shí)例方法*/
-(void)instanceMethod1;
-(void)instanceMethod2;
/*定義兩個(gè)公有類方法*/
+(void)ClassMethod1;
+(void)classMethod2;
@end
/*Test.m*/
#import"Test.h"
#import<o(jì)bjc/runtime.11>
@implementationTest
/*實(shí)例方法的原實(shí)現(xiàn)*/
-(void)instanceMethod1{
NSLog(@"instanceMethod1...");
}
-(void)instanceMethod2{
NSLog(@"instanceMethod2...");
}
/*類方法的原實(shí)現(xiàn)*/
+(void)classMethod1{
NSLog(@"classMethod1...");
}
+(void)classMethod2{
NSLog(@"classMethod2...");
}
@end
/*runtime代碼寫在類第一次被調(diào)用加載的時(shí)候(load方法有且只有一次會(huì)被調(diào)用)*/
+(void)load{
/*1.獲取當(dāng)前類名*/
Classclass=[selfclass];
/*2.獲取方法名(選擇器)*/
SELselInsMethodl=@selector(instanceMethod1);
SELselInsMethod2=@selector(instanceMethod2);
SELselClassMethod1=@selector(classMethod1);
SELselClassMethod2=@selector(classMethod2);
/*3.根據(jù)方法名獲取方法對(duì)象*/
MethodInsMethod1=class_getInstanceMethod(class,selInsMethod1);
MethodInsMethod2=class_getInstanceMethod(class,selInsMethod2);
MethodClassMethod1=class_getClassMethod(class,selClassMethod1);
MethodClassMethod2=class_getClassMethod(class,selClassMethod2);
/*4.交換實(shí)例方法的實(shí)現(xiàn)和類方法的實(shí)現(xiàn)*/
if(!InsMethod1||!InsMethod2){
NSLog(@"實(shí)例方法實(shí)現(xiàn)運(yùn)行時(shí)交換失敗!");
return;
}
/*交換實(shí)例方法的實(shí)現(xiàn)*/
method_exchangeImplementations(InsMethod1,InsMethod2);
if(!ClassMethod1||!ClassMethod2){
NSLog(@"類方法實(shí)珧運(yùn)行時(shí)交換失敗!");
return;
}
/*交換類方法的實(shí)現(xiàn)*/
method_exchangeImplementations(ClassMethod1,ClassMethod2);
}
測(cè)試代碼:
#import"ViewController.h"
#import"Test.h"
@implementationViewController
-(void)viewDidLoad{
[superviewDidLoad];
/*測(cè)試類方法調(diào)用*/
[TestclassMethod1];
[TestclassMethod2];
Test*test=[[Testalloc]init];
/*測(cè)試實(shí)例方法調(diào)用*/
[testinstanceMethod1];
[testinstanceMethod2];
}
@end
通過下而的輸出結(jié)果可知,兩個(gè)實(shí)例方法和類方法的實(shí)現(xiàn)都被互換了。
2017-03-0617:47:13.684SingleView[41495:1196960]classMethod2...
2017-03-0617:47:13.684SingleView[41495:1196960]classMethod1...
2017-03-0617:47:13.685SingleView[41495:1196960]instanceMethod2...
2017-03-0617:47:13.685SingleView[41495:1196960]instanceMethod1...
2.重新設(shè)置類中某個(gè)方法的實(shí)現(xiàn)
設(shè)置函數(shù):method_setImplementation(method,IMP)
理解了上面的例子,現(xiàn)在略微修改其中運(yùn)行時(shí)代碼,通過重新設(shè)置方法的實(shí)現(xiàn)來實(shí)現(xiàn)上面同樣的效果。修改部分的運(yùn)行時(shí)代碼為:
/*獲取方法的實(shí)現(xiàn)*/
IMPimpInsMethod1=method_getImplementation(InsMethod1);
IMPimpInsMethod2=method_getImplementation(InsMethod2);
IMPimpClassMethod1=method_getImplementation(ClassMethod1);
IMPimpClassMethod2=method_getImplementation(ClassMethod2);
/*重新設(shè)置方法的實(shí)現(xiàn)*/
/*重新設(shè)置instanceMethod1的實(shí)現(xiàn)為instanceMethod2的實(shí)現(xiàn)*/
method_setImplementation(InsMethod1,impInsMethod2);
/*重新設(shè)置instanceMethod2的實(shí)現(xiàn)為instanceMethod1的實(shí)現(xiàn)*/
method_setImplementation(InsMethod2,impInsMethod1):
/*重新設(shè)置classMethod1的實(shí)現(xiàn)為classMethod2的實(shí)現(xiàn)*/
method_setImplementation(ClassMethod1,impClassMethod2);
/*重新設(shè)置classMethod2的實(shí)現(xiàn)為classMethod1的實(shí)現(xiàn)*/
method_setImplementation(ClassMethod2,impClassMethod1);
運(yùn)行后打印結(jié)果和上面方法實(shí)現(xiàn)交換的例子結(jié)果相同。
2017-03-0618:27:53.032SingleView[41879:1212691]classMethod2...
2017-03-0618:27:53.032SingleView[41879:1212691]classMethod1...
2017-03-0618:27:53.033SingleView[41879:1212691]instanceMethod2...
2017-03-0618:27:53.033SingleView[41879:1212691]instanceMethod1...
3.替換類中某個(gè)方法的實(shí)現(xiàn)
替換方法實(shí)現(xiàn)函數(shù):class_replaceMethod(Classcls,SELname,IMPimp,constchar*types)。
這種方法只能替換實(shí)例方法的實(shí)現(xiàn),而不能替換類方法的實(shí)現(xiàn),修改的代碼如下:
/*獲取方法編碼類型*/
constchar*typeInsMethod1=method_getTypeEncoding(InsMethod1);
constchar*typeInsMethod2=method_getTypeEncoding(InsMethod2);
constchar*typeClassMethod1=method_getTypeEncoding(ClassMethod1);
constchar*typeClassMethod2=method_getTypeEncoding(ClassMethod2);
/*替換InsMethod1的實(shí)現(xiàn)為InsMethod2的實(shí)現(xiàn)*/
class_replaceMethod(class,selInsMethod1,impInsMethod2,typeInsMethod2);
/*替換InsMethod2的實(shí)現(xiàn)為InsMethod1的實(shí)現(xiàn)*/
class_replaceMethod(class,selInsMethod2,impInsMethod1,typeInsMethod1);
/*嘗試替換類方法的實(shí)現(xiàn)*/
class_replaceMethod(class,selClassMethod1,impClassMethod2,typeClassMethod2);
class_replaceMethod(class,selClassMethod2,impClassMethod1,typeClassMethod1);
通過結(jié)果可見實(shí)例方法的實(shí)現(xiàn)成功被替換,而類方法的實(shí)現(xiàn)沒有被替換。
2017-03-0618:47:03.598SingleView[42106:1221468]classMethod1...
2017-03-0618:47:03.599SingleView[42106:1221468]classMethod2...
2017-03-0618:47:03.600SingleView[42106:1221468]instanceMethod2...
2017-03-0618:47:03.600SingleView[42106:1221468]instanceMethod1...
以上介紹的是同一個(gè)類中方法實(shí)現(xiàn)的再改動(dòng),實(shí)際上也可以修改或交換不同類之間方法的實(shí)現(xiàn)。
4.在運(yùn)行時(shí)為類添加新的方法
添加函數(shù):class_addMethod()。
除了在編譯期顯式的定義方法,還可以在運(yùn)行時(shí)補(bǔ)加新的實(shí)例方法,但不可以添加新的類方法。這里接上面的例子為Test類在運(yùn)行時(shí)添加一個(gè)新的名為newInsMethod的方法,方法的實(shí)現(xiàn)設(shè)置為InsMethod1的實(shí)現(xiàn),修改后的運(yùn)行時(shí)代碼如下:
/*6.為類添加新的實(shí)例方法和類方法*/
SELselNewInsMethod=@selector(newInsMethod);
BOOL
isInsAdded=class_addMethod(class,selNewInsMethod,impInsMethod1,typeInsMethod1);
if(!isInsAdded){
NSLog(@"新實(shí)例方法添加失敗!");
}
測(cè)試新函數(shù)代碼如下:
/*測(cè)試運(yùn)行時(shí)新添加實(shí)例方法調(diào)用*/
Test*test=[[Testalloc]init];
[testnewInsMethod];
運(yùn)行結(jié)果打印出“instanceMethod1...”證明新實(shí)例方法動(dòng)態(tài)添加成功。
2017-03-0619:07:15.447SingleView[42354:1230571]instanceMethod1...
此外,除了在運(yùn)行時(shí)為類添加新的方法,還可以通過其他運(yùn)行時(shí)函數(shù)classaddIvar、classaddProperty、class_addProtocol等動(dòng)態(tài)地為類添加新的變量、屬性和協(xié)議等。
6.
如何使用runtime進(jìn)行方法交換?正確答案:runtime中的MethodSwizzling被稱為黑魔法,它可以將兩個(gè)方法的實(shí)現(xiàn)交換。類的方法列表會(huì)將selector的名稱映射到相關(guān)的方法實(shí)現(xiàn)上,使得“消息傳遞系統(tǒng)”能夠據(jù)此找到應(yīng)該調(diào)用的方法。這些方法均是以函數(shù)指針的形式來表示的,這種函數(shù)指針叫作IMP。例如NSString類的selector映射表,如圖所示。
NSString類的selector映射表
runtime中提供了幾個(gè)函數(shù)用來操作selector映射表,其中就有動(dòng)態(tài)交換兩個(gè)方法實(shí)現(xiàn)的函數(shù),代碼如下:
voidmethod_exchangeImplementations(Methodm1,Methodm2)
下面在類的Category中定義description方法,當(dāng)使用NSLog()函數(shù)輸出對(duì)象時(shí),就會(huì)調(diào)用這個(gè)方法。示例代碼如下:
/*load方法會(huì)在類第一次被加載的時(shí)候調(diào)用*/
+(void)load{
Methoddescription=class_getInstanceMethod([selfclass],@selector(description));
MethodmyDescription=class_getInstanceMethod([selfclass],@selector(myDescription));
method_exchangeImplementations(description,myDescription);
}
/*替換的方法*/
-(NSString*)myDescription{
return[NSStringstringWithFormat:@"這是自定義的打印方法"];
}
/*在控制器輸出*/
aperson=[[Personalloc]init];
NSLog(@"%@",aperson);
程序的打印結(jié)果如下:
2016-11-0320:02:59.18401[2990:170401]這是自定義的打印方法
通過MethodSwizzling可以為一些完全不知道其具體實(shí)現(xiàn)的黑盒方法增加日志記錄功能,利于開發(fā)者調(diào)試程序。并且開發(fā)者可以將某些系統(tǒng)類的具體實(shí)現(xiàn)換成自定義的方法,以達(dá)到某些目的。
7.
C和Objective-C如何混用?正確答案:Objective-C的編譯器主要可以識(shí)別以下幾種擴(kuò)展名的文件。
1).m文件:可以編寫Objective-C代碼或者C語(yǔ)言代碼。
2).cpp文件:C++文件,只能識(shí)別C++或者C語(yǔ)言代碼(C++兼容C)。
3).mm文件:主要用于編寫C++和Objective-C混編的代碼,可以同時(shí)識(shí)別Objective-C、C和C++代碼。
因此,C和Objective-C是在.m文件中實(shí)現(xiàn)混編的,當(dāng)然在.mm文件中也可以。C++和Objective-C只能是在.mm文件中實(shí)現(xiàn)混編。通過實(shí)現(xiàn)代碼混編,可以將兩種以上語(yǔ)言對(duì)接起來,從而實(shí)現(xiàn)跨平臺(tái)的對(duì)接通信。例如,可以使用C或C++語(yǔ)言與Objective-C對(duì)接,將Objective-C的原生iOS平臺(tái)接口封裝起來,供其他語(yǔ)言或平臺(tái)調(diào)用,即可實(shí)現(xiàn)跨平臺(tái)的通信。
8.
Swift和Objective-C如何互調(diào)?正確答案:Swift和Objective-C之間的互調(diào)很簡(jiǎn)單,iOS8以后蘋果公司給出了這兩種語(yǔ)言之間的橋接方案,簡(jiǎn)單來說就是在Swift工程中,通過提示創(chuàng)建的Bridging頭文件可以將Objective-C文件和Swift文件銜接在一起,從而可以在Objective-C文件中引用Swift類,或者在Swift文件中引用Objective-C的類。應(yīng)用較多的主要是在Swift中調(diào)用Objective-C類,使得在最新的Swift工程中仍然能夠兼容使用以前的Objective-C類庫(kù)等。
這里通過一個(gè)簡(jiǎn)單的例子展示在Swift工程中Objective-C和Swift之間的互調(diào)。
先建立一個(gè)Swift工程,這里創(chuàng)建了一個(gè)SingleViewApplication,工程名為SwiftBridge,并分別新建了一個(gè)新的名為SwiftClass的swift類文件和一個(gè)名為OCClass的Objective-C類文件,創(chuàng)建第一個(gè)Objective-C文件后會(huì)提示創(chuàng)建一個(gè)Bridging頭文件,創(chuàng)建后就可以對(duì)兩者進(jìn)行橋接,如圖1和圖2所示。
圖1
創(chuàng)建一個(gè)Objective-C文件
圖2
Bridging頭文件
這里在ViewController.swifi中調(diào)用OCClass類,同時(shí)在OCClass類中調(diào)用SwiftClass.swift。其中,在swift文件中引用Objective-C類時(shí)要在Bridging頭文件中引入Objective-C類的頭文件(swift文件中沒有頭文件及其引用),而在Objective-C中引用swift類時(shí)直接引入SwiftBridge-swift.h即可,不需要在Bridging頭文件設(shè)置。其中,SwiftBridge為工程名,該文件是隱藏的,對(duì)工程中所有swift類文件進(jìn)行了向Objective-C語(yǔ)言的翻譯,從而在Objective-C文件中可以像調(diào)用其他Objective-C文件一樣調(diào)用工程中的swift類文件。
1)在SwiftClass.swift中定義一個(gè)實(shí)例方法和一個(gè)類方法。
importUIKit
classSwiftClass:NSObject{
funcSwiftInstanceMethod()->Void{
print("swiftinstancemethod!");
}
classfuncSwiftClassMethod()->Void{
print("swiftclassmethod!");
}
}
2)在OCClass類中調(diào)用SwiftClass。
/*OCClass.h*/
#import<Foundation/Foundation.h>
@interfaceOCClass:NSObject
-(void)OCInstanceMethod;
+(void)OCClassMethod;
@end
/*OCClass.m*/
#import"OCClass.h"
#import"SwiftBridge-swift.h"/*引入swift類頭文件*/
@implementationOCClass
-(void)OCInstanceMethod{
/*調(diào)用swift實(shí)例方法*/
SwiflClass*swific=[[SwiftClassalloc]init];
[swiffcSwiftInstanceMethod];
NSLog(@"ocinstancemethod!");
}
+(void)OCClassMethod{
/*調(diào)用swift類方法*/
[SwiftClassSwiftClassMethod];
NSLog(@"occlassmethod!'');
}
@end
3)在Bridging頭文件引入Objective-C類頭文件供swift類調(diào)用。
/*SwiftBridge-swift.h*/
#import"OCClass.h"
4)在ViewController.swift中調(diào)用OCClass類。
/*ViewController.swift*/
importUIKit
classViewController:UIViewController{
overridefuncviewDidLoad(){
super.viewDidLoad()
letocc=OCClass()
occ.ocInstanceMethod()
OCClass.ocClassMethod()
}
}
程序的打印結(jié)果如下:
swiftinstancemethod!
2017-04-1212:40:39.657SwiftBridge[3773:5420107]ocinstancemethod!
swiftclassmethod!
2017-04-1212:40:39.657SwiftBridge[3773:5420107]occlassmethod!
另外,類似的也可以實(shí)現(xiàn)Swift和C語(yǔ)言之間的互調(diào)。
9.
Objective-C對(duì)象可以被copy的條件是什么?正確答案:Objective-C對(duì)象可以被復(fù)制的條件是要遵守NSCopying和NSMutableCoping協(xié)議,默認(rèn)是不遵守的。可以向遵守NSCopying協(xié)議的類的實(shí)例發(fā)送copy消息,也可以向遵守NSMutableCopying協(xié)議的類的實(shí)例發(fā)送mutableCopy消息,如果沒有遵守協(xié)議而發(fā)送copy或mutableCopy消息,那么就會(huì)出錯(cuò)。兩個(gè)協(xié)議分別對(duì)應(yīng)不可變復(fù)制(copy)和可變復(fù)制(mutableCopy),而協(xié)議內(nèi)部的實(shí)現(xiàn)方式?jīng)Q定是深拷貝還是淺拷貝。
例如,典型的系統(tǒng)類NSAnay是同時(shí)遵守了NSCopying和NSMutableCopying協(xié)議的,因此既可以發(fā)送copy消息,也可以發(fā)送mutableCopy消息。此外,iOS中同時(shí)遵守NSCopying協(xié)議和NSMutableCopying協(xié)議的類還有:NSString、NSValue、NSDictionary和NSSet及其子類。
如果想自定義深拷貝或淺拷貝方法,那么就要先遵守對(duì)應(yīng)的協(xié)議,并重新實(shí)現(xiàn)對(duì)應(yīng)的協(xié)議方法。
NSCopying的協(xié)議方法為copyWithZone:
-(id)copyWithZone:(nullableNSZone*)zone{
//深拷貝或淺拷貝實(shí)現(xiàn)
}
NSMutableCopying的協(xié)議方法為mutableCopyWithZone:
-(id)mutableCopyWithZone:(nullableNSZone*)zone{
//深拷貝或淺拷貝實(shí)現(xiàn)
}
10.
Objective-C等同性中的字符串相等如何判斷?正確答案:有如下代碼:
NSS
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 優(yōu)待證合作協(xié)議文本
- 2025版土地抵押權(quán)抵押權(quán)抵押權(quán)抵押資產(chǎn)證券化合同模板3篇
- 2025年度智能家居系統(tǒng)研發(fā)與裝修設(shè)計(jì)合同2篇
- 2025年全球及中國(guó)1-戊基-1H-吲哚行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年全球及中國(guó)汽車雙面膠帶行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年全球及中國(guó)流媒體音視頻產(chǎn)品行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025-2030全球船底噴氣推進(jìn)系統(tǒng)行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 2025年全球及中國(guó)游戲設(shè)計(jì)服務(wù)行業(yè)頭部企業(yè)市場(chǎng)占有率及排名調(diào)研報(bào)告
- 2025年度股權(quán)代持與風(fēng)險(xiǎn)控制協(xié)議書(個(gè)人股權(quán)轉(zhuǎn)讓與代持)4篇
- 2025年度大學(xué)學(xué)生心理健康服務(wù)合作協(xié)議
- 張家界喀斯特地貌
- 讓學(xué)生看見你的愛
- 12123交管學(xué)法減分練習(xí)題及答案二(帶圖文通用版)
- 銷售禮盒營(yíng)銷方案
- 南潯至臨安公路(南潯至練市段)公路工程環(huán)境影響報(bào)告
- 《小英雄雨來》讀書分享會(huì)
- 初中數(shù)學(xué)校本教材(完整版)
- 重慶市銅梁區(qū)2024屆數(shù)學(xué)八上期末檢測(cè)試題含解析
- 中央導(dǎo)管相關(guān)血流感染防控
- 光的偏振和晶體光學(xué)基礎(chǔ)課件
- 中科大光學(xué)講義08光的偏振
評(píng)論
0/150
提交評(píng)論