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

付費(fèi)下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

iOS程序員面試分類模擬23簡答題1.

@synthesize和@dynamic各表示什么?有什么區(qū)別?正確答案:@synthesize修飾的屬性默認(rèn)情況下由系統(tǒng)自動(dòng)合成setter和getter(江南博哥)方法,除非開發(fā)者自己定義了這些方法;@synthesize經(jīng)常用來更改屬性的變量名,系統(tǒng)自動(dòng)合成時(shí)默認(rèn)變量名為_var,即在原變量名前加下畫線。

@dynamic用來明確禁止編譯器自動(dòng)合成屬性存取方法和默認(rèn)變量名_var,由程序員自己手動(dòng)編寫存取方法。

對于@synthesize和@dynamic,由于前者明確讓編譯器自動(dòng)合成存取方法和默認(rèn)變量名,而后者明確禁止編譯器自動(dòng)合成存取方法和默認(rèn)變量名,所以兩者語義沖突,不可同時(shí)使用。

2.

Oracle數(shù)據(jù)庫的一個(gè)表中有若干條數(shù)據(jù),其占用的空間為10M,如果用delete語句刪除表中所有的數(shù)據(jù),那么此時(shí)這個(gè)表所占的空間為多大?正確答案:10M。數(shù)據(jù)庫中delete操作類似于在Windows系統(tǒng)中把數(shù)據(jù)放到回收站,還可以恢復(fù)。因此,它不會(huì)立即釋放所占的存儲(chǔ)空間。如果想在刪除數(shù)據(jù)后立即釋放存儲(chǔ)空間,那么可以使用truncate命令。

3.

用戶下載一個(gè)大圖片,分成很多份下載,如何使用GCD實(shí)現(xiàn)?正確答案:使用DispatchGroup追加block到GlobalGroupQueue,這些block如果全部執(zhí)行完畢,那么就會(huì)執(zhí)行通過dispatch_group_notify添加到主隊(duì)列中的block,進(jìn)行圖片的合并處理。

dispatch_queue_tqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_group_tgroup=dispatch_group_create();

dispatch_group_async(group,queue,^{/*加載圖片1*/});

dispatch_group_async(group,queue,^{/*加載圖片2*/});

dispatch_group_async(group,queue,^{/*加載圖片3*/});

dispatch_group_notify(group,dispatch_get_main_queue(),^{

//合并圖片

});

4.

如何理解GCD死鎖?正確答案:所謂死鎖,通常指兩個(gè)操作相互等待對方完成,造成死循環(huán),于是兩個(gè)操作都無法完成,就產(chǎn)生了死鎖。下面是一個(gè)死鎖的代碼示例。

intmain(intargc,constchar*argv[]){

@autoreleasepool{

dispatch_sync(dispatch_get_main_queue(),^(void){

NSLog(@"這里死鎖了");

});

}

return0;

}

這個(gè)程序就是典型的死鎖。程序?qū)⒅麝?duì)列和一個(gè)block傳入GCD的同步函數(shù)dispatch_sync中,等待同步函數(shù)執(zhí)行,直到同步函數(shù)返回。但是事實(shí)上,這個(gè)block永遠(yuǎn)不會(huì)被執(zhí)行。因?yàn)閙ain函數(shù)是在主隊(duì)列中的,它是正在被執(zhí)行的任務(wù),而主隊(duì)列中同時(shí)只能有一個(gè)任務(wù)在執(zhí)行,也就是說只有隊(duì)頭的任務(wù)才能被執(zhí)行。由于主隊(duì)列是一個(gè)特殊的串行隊(duì)列,它嚴(yán)格遵循FIFO的原則,所以block中的任務(wù)必須等到main函數(shù)執(zhí)行完,才能被執(zhí)行。另外,dispatch_sync函數(shù)的特性是,只有block中的任務(wù)被執(zhí)行完畢,才會(huì)返回。因此,只要block不被執(zhí)行,它就不會(huì)返回。所以,在這段代碼中,main函數(shù)等待dispatch_sync函數(shù)返回,而dispatch_sync的返回又依賴block執(zhí)行完畢,block的執(zhí)行又需要等待main函數(shù)的執(zhí)行結(jié)束。這樣就造成了三方循環(huán)等待,即死鎖。

可以總結(jié)出GCD死鎖的原因大體有以下兩點(diǎn):

1)GCD函數(shù)未返回,會(huì)阻塞正在執(zhí)行的任務(wù)。這里需要強(qiáng)調(diào)的是,阻塞(blocking)和死鎖(deadlock)是不同的意思。阻塞表示A任務(wù)的執(zhí)行需要等待B任務(wù)的完成,稱作B會(huì)阻塞A,通俗來講就是強(qiáng)制等待的意思。而死鎖表示A任務(wù)和B任務(wù)相互等待,形成阻塞閉環(huán)。

2)隊(duì)列中的任務(wù)無法并發(fā)執(zhí)行。

以上兩點(diǎn),如果同時(shí)出現(xiàn),那么就會(huì)產(chǎn)生阻塞閉環(huán),形成死鎖。所以針對以上情況,只需要消除其中任何一個(gè)因素,就可以打破這個(gè)閉環(huán),避免死鎖。

解決GCD死鎖的方法有以下幾種方式:

1)使用dispatch_async函數(shù)。dispatch_async函數(shù)是異步函數(shù),具備開啟新線程的能力,但是不一定會(huì)開啟新線程。如果傳入的隊(duì)列參數(shù)是主隊(duì)列,那么任務(wù)仍然會(huì)在主線程中等待執(zhí)行,函數(shù)不會(huì)立即返回。如果傳入的隊(duì)列是普通的串行隊(duì)列或者并發(fā)隊(duì)列,那么該函數(shù)就會(huì)立即返回。

2)將有可能形成阻塞閉環(huán)的任務(wù)分別放到不同的隊(duì)列中執(zhí)行。如案例中,可以新建一個(gè)串行隊(duì)列,將block放入自己的串行隊(duì)列中,不再和main函數(shù)除以一個(gè)隊(duì)列,就能夠解決隊(duì)列阻塞,因此避免了死鎖問題。示例代碼如下:

intmain(intargc,constchar*argv[]){

@autoreleasepool{

dispatch_queueserialQueue=dispatch_queue_create("這是一個(gè)串行隊(duì)列",DISPATCH_QUEUE_SERIAL);

dispatch_sync(serialQueue,^(void){

NSLog(@"這里不會(huì)死鎖了");

});

}

return0;

}

另外,有些面試題,如“是否在主線程使用sync函數(shù)就會(huì)造成死鎖”或者“是否在主線程使用sync函數(shù),同時(shí)傳入串行隊(duì)列就會(huì)死鎖”,答案都是否定的,只要能夠真正了解GCD死鎖的原理,就能很好地回答類似問題了。

5.

能否在一個(gè)視圖控制器中嵌入兩個(gè)tableView控制器?正確答案:可以,相當(dāng)于視圖和視圖控制器的嵌套,視圖可以添加子視圖,視圖控制器也可以添加子控制器。這種情況有時(shí)會(huì)被用到而且很重要,但是有一點(diǎn)容易被忽視,就是將子視圖添加到了父視圖卻忘記將對應(yīng)的控制器作為子控制器添加到父控制器,導(dǎo)致子視圖能顯示但是不能響應(yīng)(沒有對接好控制器)。例如在當(dāng)前視圖上放一個(gè)小尺寸的表格組件,也就是在UIViewController上添加一個(gè)UITableViewController子控制器及其子view。

/*假設(shè)有3個(gè)視圖控制器,一個(gè)作為父控制器,兩個(gè)作為子控制器*/

UIViewController*superVC=[[UIViewControlleralloc]init];

UITableViewController*subVC1=[[UITableViewControlleralloc]init];

UITableViewController*subVC2=[[UITableViewControlleralloc]init];

/*將子視圖控制器添加到父視圖控制器(要注意調(diào)整子視圖的尺寸和位置合理顯示,這里忽略)*/

[superVC.viewaddSubview:subVC1.view];

[superVCaddChildViewController:subVC1];

[superVC.viewaddSubview:subVC2.view];

[superVCaddChildViewController:subVC2];

/*子視圖控制器的移除有對應(yīng)的方法,但只能是子視圖控制器主動(dòng)從父視圖控制器中移除*/

[subVC1.viewremoveFromSuperview];

[SubVC1removeFromParentViewController];

[subVC2.viewremoveFromSuperview];

[subVC2removeFromParentViewController];

此外,要注意和presentViewController方法添加子視圖控制器的區(qū)別,上面手動(dòng)添加子視圖控制器是可以自由調(diào)整子視圖的frame的(包括子視圖位置和尺寸),而presentViewController是用于頁面切換,切換后的子頁面會(huì)覆蓋整個(gè)屏幕而不可以自由調(diào)整子頁面位置和尺寸,對應(yīng)的子視圖控制器移除方法為dismissViewControllerAnimated。

/*顯示子視圖控制器,completion后的代碼塊如果不為空,那么添加結(jié)束后會(huì)觸發(fā)*/

[[parentVCpresentViewController:childVCanimated:NOcompletion:nil];

/*移除子視圖控制器,completion后的代碼塊如果不為空,那么添加結(jié)束后會(huì)觸發(fā)*/

[childVCdismissViewControllerAnimated:NOcompletion:nil];

6.

iOS應(yīng)用有哪幾種不同狀態(tài)?分別表示什么含義?正確答案:iOS應(yīng)用在整個(gè)生命周期中會(huì)有不同的狀態(tài),各狀態(tài)可能會(huì)發(fā)生相互的轉(zhuǎn)換,主要狀態(tài)有非運(yùn)行狀態(tài)、不活躍狀態(tài)、活躍狀態(tài)、后臺狀態(tài)和掛起狀態(tài)等。具體含義見表。iOS應(yīng)用的狀態(tài)及其含義狀態(tài)名稱含義非運(yùn)行狀態(tài)(NotRunningState)應(yīng)用還沒有被運(yùn)行起來(用戶沒有單擊圖標(biāo)打開應(yīng)用)或者正在運(yùn)行的過程中被系統(tǒng)中斷了的狀態(tài)不活躍狀態(tài)(InactiveState)應(yīng)用在前臺運(yùn)行但是不接受事件交互(可能在執(zhí)行一些其他的代碼任務(wù)但不需要事件交互)。應(yīng)用通常什么時(shí)候處于這種狀態(tài)喲?例如,在運(yùn)行某個(gè)應(yīng)用時(shí),用戶突然鎖屏了,或者突然強(qiáng)制轉(zhuǎn)去處理一些像來電或短信等系統(tǒng)緊急事件。通常認(rèn)為應(yīng)用在沒有事件處理的情況下都是處于這個(gè)狀態(tài)的活躍狀態(tài)(ActiveState)應(yīng)用的正常使用狀態(tài),這時(shí)候應(yīng)用在前臺運(yùn)行且接受用戶交互事件,是前臺應(yīng)用的正常狀態(tài)后臺狀態(tài)(BackgroundState)應(yīng)用被放到后臺但還可能執(zhí)行一些后臺代碼任務(wù),通常進(jìn)入到這個(gè)后臺狀態(tài)一會(huì)兒之后就會(huì)進(jìn)入下面的掛起狀態(tài),不再執(zhí)行代碼,也就是應(yīng)用先進(jìn)入后臺狀態(tài)然后進(jìn)入掛起狀態(tài)掛起狀態(tài)(SuspendedState)在掛起狀態(tài),雖然應(yīng)用放在內(nèi)存中,但是不執(zhí)行任何代碼,處于“睡眠”狀態(tài)。當(dāng)掛起的應(yīng)用太多導(dǎo)致內(nèi)存低時(shí),系統(tǒng)可能會(huì)自行清理掉掛起的應(yīng)用來騰出空間給前臺活躍的應(yīng)用

應(yīng)用狀態(tài)轉(zhuǎn)換流程如圖所示。

應(yīng)用狀態(tài)轉(zhuǎn)換流程

7.

什么是MVC設(shè)計(jì)模式?正確答案:MVC是iOS開發(fā)中一種很基礎(chǔ)的工程架構(gòu)模式,也是構(gòu)建iOS應(yīng)用的標(biāo)準(zhǔn)模式。它將數(shù)據(jù)模型、UI視圖和邏輯控制器分開并規(guī)定它們之間的通信方式,大大優(yōu)化了程序的結(jié)構(gòu)組織。

M表示Model,專門用來存儲(chǔ)對象數(shù)據(jù)的模型,一般使用一個(gè)繼承NSObject的基本類對模型的數(shù)據(jù)進(jìn)行封裝,在.h文件中聲明一些用來存放數(shù)據(jù)的屬性。在CoreData中模型即ManagedObject。

V表示View的可見元素,展示UI界面給用戶,主要為UIKit中UIView的子類,其中和用戶進(jìn)行交互的視圖元素為UIKit子類UIControl下的子類視圖,非UIControl子類的視圖不能交互。

C表示Controller,邏輯控制器,對應(yīng)于UIKit中UIViewController及其子類控制器,負(fù)責(zé)協(xié)調(diào)View和Model。

Controller和View的通信主要通過一些代理協(xié)議以及block代碼塊等實(shí)現(xiàn);而Controller和Model的通信主要用到Notification消息通知和KVO等典型觀察者模式實(shí)現(xiàn);View和Model是隔離的,不可以直接相互通信。

MVC設(shè)計(jì)模式是官方推薦在iOS開發(fā)中使用的規(guī)范模式,應(yīng)用的數(shù)據(jù)存儲(chǔ)在Model層,邏輯處理在Controller中進(jìn)行,而用戶界面在View中展示。

8.

重載、重寫和隱藏的區(qū)別是什么?正確答案:重載(overload):函數(shù)名相同,函數(shù)的參數(shù)列表不同(包括參數(shù)個(gè)數(shù)和參數(shù)類型),至于返回類型可同可不同。重載發(fā)生在同一個(gè)類的不同函數(shù)之間,是橫向的。重載和多態(tài)性無關(guān)。

重寫(override):主要指父類虛函數(shù)(虛函數(shù)是C++語言概念)的重寫,用來體現(xiàn)多態(tài)性,指子類不想繼承使用父類的方法,通過重寫同一個(gè)函數(shù)來實(shí)現(xiàn)對父類中同一個(gè)函數(shù)的覆蓋,因此又叫函數(shù)覆蓋。重寫的函數(shù)必須和父類一模一樣,包括函數(shù)名、參數(shù)個(gè)數(shù)和類型以及返回值,只是重寫了函數(shù)的實(shí)現(xiàn)。重寫發(fā)生于父類和子類之間,是縱向的。

隱藏:Objective-C中沒有隱藏,典型的C++中有,通過虛函數(shù)和父子類之間的函數(shù)重寫進(jìn)行區(qū)分,此處不再討論。其中,重載和重寫是針對函數(shù)的,而隱藏除了函數(shù)還會(huì)針對成員變量。隱藏發(fā)生在父類和子類之間,隱藏指父類的同名函數(shù)或變量在子類中隱藏,其中只要函數(shù)同名就隱藏,不管參數(shù)相同與否。在子類中父類的同名函數(shù)或變量不可見,但在父類中依然存在。

9.

Objective-C有私有方法嗎?有私有變量嗎?正確答案:Objective-C是否有私有方法和私有變量關(guān)鍵要看私有的定義。私有主要指通過類的封裝性,將不希望讓外界看到的方法或?qū)傩噪[藏在類內(nèi)部,只有該類可以在內(nèi)部訪問,外部不可見不可訪問。

表面上看,Objective-C中是可以實(shí)現(xiàn)私有的變量和方法的,即將它們隱藏不暴露在頭文件中,不可以顯式地直接訪問,但是Objective-C中這種私有并不是絕對的私有,例如即使將變量和方法隱藏在.m實(shí)現(xiàn)文件中,開發(fā)者仍然可以利用KVC或runtime運(yùn)行時(shí)機(jī)制強(qiáng)行訪問沒有暴露在頭文件的變量或方法。

Objective-C中實(shí)現(xiàn)變量和方法“私有”的方式主要有兩種。

1)在類的頭文件中聲明私有變量。

#import<Foundation/Foundation.h>

@interfaceTest:NSObject{

/*頭文件中定義私有變量,默認(rèn)為@protected*/

@private

NSString*major;

}

@end

2)在.m實(shí)現(xiàn)文件頭部的類擴(kuò)展區(qū)域定義私有屬性或方法,其中方法可不用聲明,直接在實(shí)現(xiàn)文件中實(shí)現(xiàn)即可,只要不在頭文件聲明的方法都對外不可見。

#import"Test.h"

@interfaceTest(){

/*類擴(kuò)展區(qū)域定義私有變量,默認(rèn)就是@private*/

intage;

}

/*類擴(kuò)展區(qū)域定義私有屬性*/

@property(nonatomic,copy)NSString*name;

/*類擴(kuò)展區(qū)域定義私有實(shí)例方法(可省略聲明,類方法的作用主要就是提供對外接口的,所以一般不會(huì)定義為私有)*/

-(void)test;

@end

@implementationTest

/*私有實(shí)例方法*/

-(void)test{

NSLog(@"這是個(gè)私有實(shí)例方法!");

}

@end

利用KVC和runtime暴力訪問私有屬性和變量

KVC訪問變量不受私有權(quán)限的限制,訪問代碼如下:

#import"Test.h"

#import<o(jì)bjc/runtime.h>

...

Test*test=[[Testalloc]ink];

/*1.KVO暴力訪問私有屬性和私有變量*/

[testsetValue:@"albert"forKeyPath:@"name"];

NSString*pname=[testvalueForKey:@"name"];

[testsetValue:@"mathmetics"forKeyPath:@"major"];

NSString*pmajor=[testvalueForKey:@"major"];

NSLog(@"pname:%@pmajor:%@",pname,pmajor);

程序的運(yùn)行結(jié)果為:

2017-04-0211:58:56.255723CommandLine[99973:3239125]pname:albertpmajor:mathmetics

運(yùn)行時(shí)可以使用class_copyIvarList函數(shù)獲取類對象的Ivar變量列表,然后可使用object_getIvar和object_setIvar運(yùn)行時(shí)函數(shù)對變量進(jìn)行暴力訪問。

#import"Test.h"

#import<o(jì)bjc/runtime.h>

...

Test*test=[[Testalloc]init];

/*2.運(yùn)行時(shí)暴力訪問私有屬性和私有變量(ARC)*/

/*獲取實(shí)例變量列表*/

unsignedintcount=0;

Ivar*members=class_copyIvarList([Testclass],&count);

/*打印所有的變量名及其類型*/

for(inti=0;i<count;i++){

constchar*memberName=ivar_getName(members[i]);

constchar*memberType=ivar_getTypeEncoding(members[i]);

NSLog(@"name:%stype:%s",memberName,memberType);

}

/*訪問私有屬性和變量*/

Ivarvarname=members[0];

Ivarvarmajor=members[1];

object_setIvar(test,varname,@"albert");

object_setIvar(test,varmajor,@"mathmetics");

NSString*name=object_getIvar(test,varname);

NSString*major=object_getIvar(test,varmajor);

NSLog(@"pname:%@",name);

NSLog(@"pmajor:%@",major);

/*要手動(dòng)釋放*/

free(members);

程序的運(yùn)行結(jié)果為:

2017-04-0212:07:22.105758CommandLine[189:3242353]name:majortype:@"NSString"

2017-04-0212:07:22.105930CommandLine[189:3242353]name:_nametype:@"NSString"

2017-04-0212:07:22.106156CommandLine[189:3242353]pname:albert

2017-04-0212:07:22.106221CommandLine[189:3242353]pmajor:mathmetics

Runtime暴力訪問對象私有方法

和訪問私有變量類似,這里使用class_copyMethodList運(yùn)行時(shí)函數(shù)獲取類對象中的方法列表,然后使用performSelector函數(shù)執(zhí)行某個(gè)方法。這里只展示了實(shí)例方法的訪問,類方法的訪問也類似,另外還可以使用class_addMethod運(yùn)行時(shí)函數(shù)往類對象中強(qiáng)行添加新的方法,具體見MethodSwizzling部分。

#import"Test.h"

#import<o(jì)bjc/runtime.h>

...

Test*test=[[Testalloc]init];

/*運(yùn)行時(shí)暴力訪問私有方法*/

/*獲取類對象方法列表*/

unsignedintcount=0:

Method*methods=class_copyMethodList([Testclass],&count);

/*獲取第一個(gè)方法的方法名*/

SELsel=method_getName(methods[0]);

/*執(zhí)行該方法*/

[testperformSelector:sel];

10.

如何理解多線程?正確答案:多線程(multithreading)指從軟件或者硬件上實(shí)現(xiàn)多個(gè)線程并發(fā)執(zhí)行的技術(shù)。具有多線程能力的計(jì)算機(jī)因有硬件的支持而能夠在同一時(shí)間執(zhí)行多個(gè)線程,進(jìn)而提升整體處理性能。要深入了解iOS中的多線程技術(shù),先需要了解以下幾個(gè)概念。

1.進(jìn)程

每個(gè)正在系統(tǒng)上運(yùn)行的程序都是一個(gè)進(jìn)程。每個(gè)進(jìn)程之間是相互獨(dú)立的,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間內(nèi)。進(jìn)程在系統(tǒng)內(nèi)存中的關(guān)系如圖所示。

系統(tǒng)內(nèi)存中的進(jìn)程

通過“活動(dòng)監(jiān)視器”可以查看Mac系統(tǒng)中開啟的所有進(jìn)程(見圖)。

活動(dòng)監(jiān)視器中的進(jìn)程

2.線程

線程是一組指令的集合,或者是程序的特殊段,它可以在程序里獨(dú)立執(zhí)行。每個(gè)進(jìn)程包含至少一個(gè)線程。線程基本上是輕量級的進(jìn)程,它負(fù)責(zé)在單個(gè)程序中執(zhí)行多個(gè)任務(wù)。通常由系統(tǒng)負(fù)責(zé)多個(gè)線程的調(diào)度和執(zhí)行。

需要注意的是,在同一個(gè)線程中執(zhí)行的任務(wù)是串行的。也就是說,在同一時(shí)間內(nèi),一個(gè)線程只能執(zhí)行一個(gè)任務(wù)。

線程是程序中一個(gè)單一的順序控制流程。在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的工作,稱為多線程。多線程技術(shù)主要是為了充分利用CPU,提高程序的執(zhí)行效率。多線程之間的關(guān)系如圖所示。

多線程之間的關(guān)系

事實(shí)上,在同一時(shí)間,CPU只能處理一條線程,只有一條線程在執(zhí)行。多線程的并發(fā)執(zhí)行,其實(shí)就是CPU快速地在多條線程之間調(diào)度。如果CPU調(diào)度線程的速度足夠快,那么就會(huì)產(chǎn)生多條線程并發(fā)執(zhí)行的假象。

多線程技術(shù)的優(yōu)點(diǎn)如下:

1)可以很大程度上提高程序的執(zhí)行效率,提高程序的響應(yīng)速度。

2)使用線程可以把占據(jù)時(shí)間長的程序中的任務(wù)放到后臺去處理,這樣就不會(huì)阻塞程序主線程,用戶體驗(yàn)更好(耗時(shí)操作會(huì)卡住主線程,嚴(yán)重影響UI的流暢度)。

3)提高計(jì)算機(jī)資源的利用率,如:更加充分利用內(nèi)存,多CPU計(jì)算機(jī)上提高CPU利用率。

4)將進(jìn)程分塊,優(yōu)化簡化程序邏輯結(jié)構(gòu)。

多線程技術(shù)的缺點(diǎn)如下:

1)多線程程序的代碼會(huì)更加復(fù)雜、難讀,增加交接和維護(hù)難度。

2)創(chuàng)建和調(diào)度線程會(huì)有額外的開銷,線程越多,開銷越大,甚至反而降低程序的性能。

3)通常模型數(shù)據(jù)是在多個(gè)線程間共享的,需要防止線程死鎖情況的發(fā)生。

因此,在實(shí)際使用多線程時(shí),需要適當(dāng)開啟線程,當(dāng)線程使用完成后,需要及時(shí)釋放資源。在最新的iOS技術(shù)中,已經(jīng)很少需要直接操作線程了,因?yàn)樘O果公司已經(jīng)將大部分復(fù)雜的操作封裝好。

11.

CATransition中過渡類型動(dòng)畫有哪幾種type?正確答案:CATransition是CoreAnimation框架提供的轉(zhuǎn)場動(dòng)畫類。開發(fā)者可以通過一組預(yù)定義的轉(zhuǎn)換或者定制的CIFilter實(shí)例來指定轉(zhuǎn)場效果。下面的代碼演示了當(dāng)單擊tabBar按鈕時(shí)的界面切換動(dòng)畫。

-(void)tabBar:(UITabBar*)tabBardidSelectItem:(UITabBarItem*)item{

CATransition*animation=[CATransitionanimation];

animation.duration=0.5:

/*指定效果*/

animation.type=@"reveal";

/*指定效果展示方向*/

animation.subtype=@"fromBottom";

[self.view.layeraddAnimation:animationforKey:nil];

}

其中的type屬性是一個(gè)NSString類型的字符串,指定了轉(zhuǎn)場動(dòng)畫的類型。它有4個(gè)效果可供選擇:

1)fade:淡入淡出的過渡效果。對應(yīng)常量kCATransitionFade。

2)moveIn:新視圖移動(dòng)到舊視圖的上面。對應(yīng)常量kCATransitionMoveIn。

3)push:新視圖將舊視圖推出窗口。對應(yīng)常量kCATransitionPush。

4)reveal:舊視圖移開顯示下面的新視圖。對應(yīng)常量kCATransitionReveal。

需要注意的是,以上4種效果都暴露在CATransition的.h頭文件中,可以安全使用。除此之外,還有一些效果屬于iOS私有的API,在使用這些效果后,應(yīng)用在審核時(shí)有一定被拒絕的風(fēng)險(xiǎn)。這些效果包括:

1)cube:立方體效果。

2)oglFlip:翻轉(zhuǎn)效果。

3)suckEffect:收縮效果。

4)rippleEffect:水滴波紋效果。

5)pageCurl:向上翻頁效果。

6)pageUnCurl:向下翻頁效果。

7)cameraIrisHollowOpen:攝像頭打開效果。

8)cameraIrisHollowClose:攝像頭關(guān)閉效果。

12.

常量和變量有什么區(qū)別?正確答案:在Objective-C中,用來指代數(shù)據(jù)的值有可變和不可變之分。常量表示一些固定的、不會(huì)被修改的數(shù)據(jù)。反之,能改變的數(shù)據(jù)的值就稱為變量。

常量的屬性決定了常量一旦賦值后就不能進(jìn)行二次賦值了,只能讀取數(shù)據(jù),不能再次寫入數(shù)據(jù),每個(gè)常量都必須有唯一的名字和內(nèi)存空間。變量的特性就是可以多次改變值。在程序執(zhí)行期間,變量的值可以隨意改變。

13.

UIKit類要在哪一個(gè)應(yīng)用線程上使用?正確答案:UIKit的界面類只能在主線程上使用,對界面進(jìn)行更新,多線程環(huán)境中要對界面進(jìn)行更新必須要切換到主線程上。

例如下面的問題代碼:

@interfaceTTWaitController:UIViewController

@property(strong,nonatomic)UILabel*alert;

@end

@implementationTTWaitController

-(void)TiewDidLoad

{

CGRectframe=CGRectMake(20,200,200,20);

self.alert=[[UILabelalloc]initWithFrame:frame];

self.alert.text=@"Pleasewait10seconds...";

self.alert.textColor=[UIColorwhiteColor];

[self.viewaddSubview:self.aleft];

NSOperationQueue*waitQueue=[[NSOperationQueuealloc]init];

[waitQueueaddOperationWithBlock:^{

[NSThreadsleepUntilDate:[NSDatedateWithTimeIntervalSinceNow:10]];

self.alert.text=@"Thanks!";

}];

}

@end

@implementationTTAppDelegate

-(BOOL)application:(UIApplication*)application

didFinishLaunchingWithOptions:(NSDictionary*)launchOptions

{

self.window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];

self.window.rootViewController=[[TTWaitControlleralloc]init];

[self.windowmakeKeyAndVisible];

returnYES;

}

這段代碼是想提醒用戶等待10s,10s后在標(biāo)簽上顯示“Thanks”,但多線程代碼部分NSOperationQueue的addOperationWithBlock函數(shù)不能保證block里面的語句是在主線程中運(yùn)行的,UILabel顯示文字屬于UI更新,必須要在主線程進(jìn)行,否則會(huì)有未知的操作,無法在界面上及時(shí)正常顯示。

解決方法是將UI更新的代碼寫在主線程上。代碼同步到主線程上主要有3種方法:NSThread、NSOperationQueue和GCD,3個(gè)層次的多線程都可以獲取主線程并同步。

14.

如何理解MVC設(shè)計(jì)模式?正確答案:MVC全名是ModelViewController,是模型(Model)一界面視圖(View)一控制器(Controller)的縮寫,它是一種軟件設(shè)計(jì)規(guī)范,用一種將業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到Controller中,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要編寫業(yè)務(wù)邏輯。可以用下圖來描述通過控制器實(shí)現(xiàn)的視圖到模型的交互過程。

MVC設(shè)計(jì)模式結(jié)構(gòu)

1.模型對象

模型對象封裝了應(yīng)用程序的數(shù)據(jù),并定義了操控和處理該數(shù)據(jù)的邏輯和運(yùn)算規(guī)則。用戶在視圖層中所進(jìn)行的創(chuàng)建或者修改數(shù)據(jù)的操作,會(huì)通過控制器對象傳達(dá)出去,最終會(huì)創(chuàng)建或更新模型對象。另外,當(dāng)模型對象更改時(shí)(例如,通過網(wǎng)絡(luò)連接接收到新數(shù)據(jù)),模型對象會(huì)通知控制器對象,控制器對象更新相應(yīng)的視圖對象。被模型返回的數(shù)據(jù)是中立的,也就是說模型和數(shù)據(jù)格式無關(guān),這樣一個(gè)模型能為多個(gè)視圖提供數(shù)據(jù)。由于應(yīng)用于模型的代碼只需要寫一次就可以被多個(gè)視圖重用,所以減少了代碼的重復(fù)性。

2.視圖對象

視圖對象是應(yīng)用程序中用戶可以看到并且能夠與之交互的界面。視圖對象對外提供顯示自身和響應(yīng)用戶操作的接口。視圖對象的主要作用就是顯示來自應(yīng)用程序模型對象的數(shù)據(jù),并使該數(shù)據(jù)可被編輯。在iOS應(yīng)用程序開發(fā)中,所有的控件、窗口等都繼承自UIView,對應(yīng)于MVC中的View。

3.控制器對象

在應(yīng)用程序的一個(gè)或多個(gè)視圖對象和一個(gè)或多個(gè)模型對象之間,控制器對象充當(dāng)媒介。因此,控制器對象是同步管理程序,通過控制器對象,視圖對象了解模型對象的更改,反之亦然??刂破鲗ο筮€可以為應(yīng)用程序執(zhí)行設(shè)置和協(xié)調(diào)任務(wù),并管理其他對象的生命周期??刂破鲗ο蠼忉屧谝晥D對象中進(jìn)行的用戶操作,并將新的或更改過的數(shù)據(jù)傳達(dá)給模型對象。模型對象更改時(shí),一個(gè)控制器對象會(huì)將新的模型數(shù)據(jù)傳達(dá)給視圖對象,以便視圖對象可以顯示它。

MVC設(shè)計(jì)模式的低耦合性、高重用性、可維護(hù)性等優(yōu)點(diǎn)顯而易見,使得原本復(fù)雜的代碼與界面的交互變得簡單、清晰、明了,開發(fā)者可以把更多的精力放在前端界面的設(shè)計(jì)上,而不用絞盡腦汁去思考究竟應(yīng)該如何使界面得到同步,這樣減輕了設(shè)計(jì)壓力,也從另一方面使用戶得到更多更好的享受體驗(yàn)。事實(shí)上,MVC設(shè)計(jì)模式也是蘋果公司推薦并在大量實(shí)踐的設(shè)計(jì)模式。例如,對于不同的UIView類型的視圖對象,都有相應(yīng)地控制器對象(即UIViewController)與之對應(yīng)。例如,常用的視圖類UITableView,它所對應(yīng)的控制器對象就是UITableViewController類對象。

15.

如何使用NSURLSession進(jìn)行網(wǎng)絡(luò)請求?正確答案:在2013年的WWDC上,蘋果公司推出了NSURLConnection的替代方案:NSURLSession。和NSURLConnection一樣,NSURLSession指的也不僅是同名類NSURLSession,它還包括一系列相關(guān)聯(lián)的類。NSURLSession包括了與之前相同的組件:NSURLRequest與NSURLCache,但是將NSURLConnection替換成了NSURLSession、NSURLSessionConfiguration及NSURLSessionTask的3個(gè)子類:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。

與NSURLConnection相比,NSURLSession最直接的改進(jìn)就是可以配置每個(gè)session的緩存、協(xié)議、cookie,以及證書策略(CredentialPolicy),甚至跨進(jìn)程共享這些信息。這將允許程序和網(wǎng)絡(luò)基礎(chǔ)框架之間相互獨(dú)立,不會(huì)發(fā)生干擾。每個(gè)NSURLSession對象都由一個(gè)NSURLSessionConfiguration對象進(jìn)行初始化,后者指定了剛才提到的那些策略以及一些用來增強(qiáng)移動(dòng)設(shè)備上性能的新選項(xiàng)。

NSURLSessionTask負(fù)責(zé)處理數(shù)據(jù)的加載以及文件的數(shù)據(jù)在客戶端與服務(wù)器之間的上傳和下載。它是一個(gè)抽象類,一般使用其子類:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。這3個(gè)子類封裝了現(xiàn)代程序3個(gè)最基本的網(wǎng)絡(luò)任務(wù):獲取數(shù)據(jù)(如JSON或者XML),上傳文件和下載文件。

NSURLSession相關(guān)類的關(guān)系如圖所示。

NSURLSession相關(guān)類的關(guān)系

如何使用NSURLSession像NSURLConnection那樣發(fā)送一個(gè)請求呢?基本步驟如下:

1)創(chuàng)建NSURLSessionConfiguration對象對NSURLSession進(jìn)行配置。

2)創(chuàng)建NSURLSession對象。

3)利用上一步創(chuàng)建好的NSURLSession對象創(chuàng)建NSURLSessionTask的子類對象。

4)執(zhí)行請求任務(wù)。

下面的示例展示了NSURLSession的基本用法,代碼如下:

-(void)sessionGet{

/*創(chuàng)建NSURL對象*/

NSURL*url=[NSURLURLWithString:IMAGEURL];

/*創(chuàng)建請求對象,默認(rèn)為GET請求*/

NSURLRequest*request=[NSURLRequestrequestWithURL:url];

/*創(chuàng)建配置*/

NSURLSessionConfiguration*config=[NSURLSessionConfigurationdefaultSessionConfigtwation];

/*創(chuàng)建NSURLSession對象*/

NSURLSession*session=[NSURLSessionsessionWithConfiguration:config];

/*創(chuàng)建任務(wù)*/

NSURLSessionDataTask*task=[sessiondataTaskWithRequest:requestcompletionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullableresponse,NSError*_Nullableerror){

if(error){

return;

}

/*解析返回的數(shù)據(jù)*/

_image=[UIImageimageWithData:data];

/*顯示圖片,注意!此時(shí)是異步線程需要在主線程中顯示圖片*/

[selfchangeBg];

}];

[taskresume];

}

16.

QuartzCore和CoreGraphics有什么區(qū)別?正確答案:CoreGra

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論