iOS程序員面試分類模擬6_第1頁(yè)
iOS程序員面試分類模擬6_第2頁(yè)
iOS程序員面試分類模擬6_第3頁(yè)
iOS程序員面試分類模擬6_第4頁(yè)
iOS程序員面試分類模擬6_第5頁(yè)
已閱讀5頁(yè),還剩13頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論