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

下載本文檔

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

文檔簡介

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

GCD中有哪幾種隊(duì)列?正確答案:在GCD中,派發(fā)隊(duì)列(DispatchQueue)是最重要的概念之一。派發(fā)隊(duì)列是一個(gè)對象,它可以接受任務(wù),并將任務(wù)以FIF(江南博哥)O(先進(jìn)先出)的順序來執(zhí)行。派發(fā)隊(duì)列可以是并發(fā)的或串行的。并發(fā)隊(duì)列可以執(zhí)行多任務(wù),串行隊(duì)列同一時(shí)間只執(zhí)行單一任務(wù)。在GCD中,有3種類型的派發(fā)隊(duì)列。

1)串行隊(duì)列。串行隊(duì)列中的任務(wù)按先后順序逐個(gè)執(zhí)行,通常用于同步訪問一個(gè)特定的資源。使用dispatch_queue_create函數(shù),可以創(chuàng)建串行隊(duì)列。

2)并發(fā)隊(duì)列。在GCD中也稱為全局并發(fā)隊(duì)列,可以并發(fā)地執(zhí)行一個(gè)或者多個(gè)任務(wù)。并發(fā)隊(duì)列有高、中、低、后臺4個(gè)優(yōu)先級別,中級是默認(rèn)級別??梢允褂胐ispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)函數(shù)來獲取全局并發(fā)隊(duì)列對象。串行隊(duì)列和異步隊(duì)列的區(qū)別在于同步執(zhí)行和異步執(zhí)行時(shí)的表現(xiàn)(見表)。串行隊(duì)列和異步隊(duì)列的區(qū)別

同步執(zhí)行異步執(zhí)行串行隊(duì)列在當(dāng)前線程中,F(xiàn)IFO執(zhí)行在其它線程,F(xiàn)IFO執(zhí)行并發(fā)隊(duì)列在當(dāng)前線程中,F(xiàn)IFO執(zhí)行多條線程,同步執(zhí)行

3)主隊(duì)列。它是一種特殊的串行隊(duì)列。它在應(yīng)用程序的主線程中用于更新UI。其他的兩種隊(duì)列不能更新UI。使用dispatch_get_main_queue函數(shù),可以獲得主隊(duì)列對象。

2.

HTTPS協(xié)議與HTTP協(xié)議有什么區(qū)別與聯(lián)系?正確答案:HTTP協(xié)議被用于在Web瀏覽器和網(wǎng)站服務(wù)器之間傳遞信息。HTTP協(xié)議以明文方式發(fā)送內(nèi)容,不提供任何方式的數(shù)據(jù)加密,如果攻擊者截取了Web瀏覽器和網(wǎng)站服務(wù)器之間的傳輸報(bào)文,那么就可以直接讀懂其中的信息。因此,HTTP協(xié)議不適合傳輸一些敏感信息,如信用卡號、密碼等。

為了解決HTTP協(xié)議的這一缺陷,需要使用另一種協(xié)議:安全套接字層超文本傳輸協(xié)議(HTTPS)。為了數(shù)據(jù)傳輸?shù)陌踩?,HTTPS在HTTP的基礎(chǔ)上加入了SSL協(xié)議,SSL依靠證書來驗(yàn)證服務(wù)器的身份,并為瀏覽器和服務(wù)器之間的通信加密。

HTTPS和HTTP的區(qū)別主要為以下4點(diǎn):

1)HTTPS協(xié)議需要從CA(CertificateAuthority)申請一個(gè)用于證明服務(wù)器用途類型的證書,一般免費(fèi)證書很少,需要交費(fèi)。

2)HTTP是超文本傳輸協(xié)議,信息是明文傳輸,HTTPS則是具有安全性的SSL加密傳輸協(xié)議。

3)HHTP和HTTPS使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。

4)HTTP的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比HTTP協(xié)議安全。

3.

如何理解drawRect:方法?正確答案:iOS的繪圖操作是發(fā)生在UIView類的drawRect:方法中的。如果想在UIView中繪圖,那么可以通過繼承UIView類并實(shí)現(xiàn)其drawRect:方法,在drawRect:方法中獲取當(dāng)前的環(huán)境上下文(context)進(jìn)行繪制。drawRect:方法被定義在UIView的UIViewRendering類別中:

-(void)drawReet:(CGRect)rect;

drawRect:里面的代碼利用CoreGraphics在指定的rect中繪制圖形,然后內(nèi)容就會被緩存起來直到它需要被更新。事實(shí)上,蘋果公司并不建議開發(fā)者主動調(diào)用drawRect:方法,當(dāng)然如果強(qiáng)制直接調(diào)用該方法,那么也是沒有效果的,因?yàn)橄到y(tǒng)此時(shí)不會自動創(chuàng)建和View相關(guān)聯(lián)的上下文。而且當(dāng)沒有自定義繪制任務(wù)時(shí),就不要在子類中寫一個(gè)空的drawRect:,否則會造成CPU資源和內(nèi)存的浪費(fèi)。

當(dāng)視圖在屏幕中出現(xiàn)的時(shí)候,drawRect:方法就會被自動調(diào)用。具體是,drawRect:方法的第一次調(diào)用是在控制器中l(wèi)oadView和viewDidLoad兩方法之后。所以不必?fù)?dān)心在控制器初始化之前,drawRect:就會被執(zhí)行。雖然drawRect:是UIView類中的方法,但事實(shí)上都是底層的CALayer對象安排了重繪工作并保存了繪制好的內(nèi)容。

另外,可以調(diào)用setNeedsDisplay:方法將繪制好的圖形更新到視圖上。setNeedsDisplay:方法就是在receiver上設(shè)置一個(gè)需要被重新繪制的標(biāo)記,在下一個(gè)繪制周期自動進(jìn)行重繪,一般iPhone的刷新頻率為60Hz,也就是說1/60s后重繪。示例代碼如下:

-(void)drawRect:(CGRect)rect{

/*獲取上下文*/

CGContextRefctx=UIGraphicsGetCurrentContext();

/*繪制一個(gè)圓形*/

CGContextAddEllipseInRect(ctx,CGRectMake(0,0,200,200));

/*設(shè)置顏色*/

[[UIColorredColor]set];

/*填充*/

CGContextFillPath(ctx);

}

4.

Swift和Objective-C如何互調(diào)?正確答案:Swift和Objective-C之間的互調(diào)很簡單,iOS8以后蘋果公司給出了這兩種語言之間的橋接方案,簡單來說就是在Swift工程中,通過提示創(chuàng)建的Bridging頭文件可以將Objective-C文件和Swift文件銜接在一起,從而可以在Objective-C文件中引用Swift類,或者在Swift文件中引用Objective-C的類。應(yīng)用較多的主要是在Swift中調(diào)用Objective-C類,使得在最新的Swift工程中仍然能夠兼容使用以前的Objective-C類庫等。

這里通過一個(gè)簡單的例子展示在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文件后會提示創(chuàng)建一個(gè)Bridging頭文件,創(chuàng)建后就可以對兩者進(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為工程名,該文件是隱藏的,對工程中所有swift類文件進(jìn)行了向Objective-C語言的翻譯,從而在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語言之間的互調(diào)。

5.

如果數(shù)據(jù)庫日志滿了,那么會出現(xiàn)什么情況?正確答案:日志文件(LogFile)記錄所有對數(shù)據(jù)庫數(shù)據(jù)的修改,主要是保護(hù)數(shù)據(jù)庫以防止故障,以及恢復(fù)數(shù)據(jù)時(shí)使用。其特點(diǎn)如下:

1)每一個(gè)數(shù)據(jù)庫至少包含兩個(gè)日志文件組。每個(gè)日志文件組至少包含兩個(gè)日志文件成員。

2)日志文件組以循環(huán)方式進(jìn)行寫操作。

3)每一個(gè)日志文件成員對應(yīng)一個(gè)物理文件。

通過日志文件來記錄數(shù)據(jù)庫事務(wù)可以最大限度地保證數(shù)據(jù)的一致性與安全性,但數(shù)據(jù)庫中日志滿了,就只能執(zhí)行查詢等讀操作,不能執(zhí)行更改、備份等操作,原因是任何寫操作都要記錄日志,也就是說基本上處于不能使用的狀態(tài)。

6.

NSNotification是同步還是異步?正確答案:NSNotification默認(rèn)在主線程中通知是同步的,當(dāng)通知產(chǎn)生時(shí),通知中心會一直等待所有的觀察者都收到并且處理通知結(jié)束,然后才會返回到發(fā)送通知的地方繼續(xù)執(zhí)行后面的代碼,但可以將通知的發(fā)送或者將通知的處理方法放到子線程中從而避免通知阻塞。其中,通知的發(fā)送可以添加到NSNotificationQueue異步通知緩沖隊(duì)列中,也不會導(dǎo)致通知阻塞。NSNotificationQueue是一個(gè)通知緩沖隊(duì)列,通常以FIFO(先進(jìn)先出)的規(guī)則維護(hù)通知隊(duì)列的發(fā)送。向通知隊(duì)列添加通知有3種枚舉類型:NSPostASAP、NSPostWhenIdle和NSPostNow,分別表示盡快發(fā)送、空閑時(shí)發(fā)送和現(xiàn)在立刻發(fā)送,可以根據(jù)通知的緊急程度進(jìn)行選擇。

下面示例驗(yàn)證默認(rèn)通知是同步的。

/*自定義消息的名稱*/

#defineMYNotificationTestName@"NSNotificationTestName"

/*1.注冊通知的觀察者*/

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(process)name:MYNotificationTestNameobject:nil];

/*2.發(fā)出通知給觀察者*/

NSLog(@"即將發(fā)出通知!");

[[NSNotificationCenterdefaultCenter]postNotificationName:MYNotificationTestNameobject:nil];

NSLog(@"發(fā)出通知處的下一條代碼!");

/*3.處理收到的通知*/

-(void)process{

sleep(10);//假設(shè)處理需要10s

NSLog(@"通知處理結(jié)束!");

}

程序的打印結(jié)果為:

2017-01-2122:21:30.501SingleView[4579:146073]即將發(fā)出通知!

2017-01-2122:21:40.572SingleView[4579:146073]通知處理結(jié)束!

2017-01-2122:21:40.572SingleView[4579:t46073]發(fā)出通知處的下一條代碼!

打印“即將發(fā)出通知”后,等了10s之后才打印出“通知處理結(jié)束”,然后打印出@“發(fā)出通知處的下一條代碼!”?!鞍l(fā)出通知處的下一條代碼!”是等到通知處理結(jié)束才打印出來的,說明通知是同步的。

可以通過將通知的發(fā)送語句或者通知的處理語句放到子線程實(shí)現(xiàn)通知的異步。

將通知的發(fā)送語句放到子線程:

NSLog(@"即將發(fā)出通知!");

dispatch_async(dispatch_get_global_queue(0,0),^{

[[NSNotificationCenterdefaultCenter]

postNotificationName:MYNotificationTestNameobject:nil];

});

NSLog(@"發(fā)出通知處的下一條代碼!");

或者:

NSLog(@"即將發(fā)出通知!");

/*將通知放到通知異步緩沖隊(duì)列*/

NSNotification*notification=[NSNotificationnotificationWithName:MYNotificationTestNameobject:nil];

[[NSNotificationQueuedefaultQueue]enqueueNotification:notificationpostingStyle:NSPostASAP];

NSLog(@"發(fā)出通知處的下一條代碼!");

將通知的處理放到子線程:

/*處理收到的通知*/

-(void)process{

dispatch_async(dispatch_get_global_queue(0,0),^{

sleep(10);//假設(shè)處理需要10s

NSLog(@"通知處理結(jié)束!");

});

}

執(zhí)行結(jié)果變?yōu)椋?/p>

2017-01-2122:31:09.259SingleView[4711:151180]即將發(fā)出通知!

2017-01-2122:31:09.260SingleView[4711:151180]發(fā)出通知處的下一條代碼!

2017-01-2122:3l:19.290SingleView[4711:151252]通知處理結(jié)束!

7.

如何理解消息傳遞機(jī)制?正確答案:對Objective-C對象調(diào)用方法的操作通常稱為“消息傳遞”。在Objective-C中,如果向某對象傳遞消息,那么就會使用動態(tài)綁定機(jī)制來決定需要調(diào)用的方法。在底層,所有方法都是普通的C語言函數(shù),然而對象收到消息之后,究竟該調(diào)用哪個(gè)方法則完全由runtime來決定,有時(shí)甚至可以在運(yùn)行期改變方法的實(shí)現(xiàn)。

在代碼中給對象發(fā)送消息可以這樣來編寫:

[receivermessageName:parameter];

消息的接收者(receiver)和參數(shù)(parameter)合起來稱為“消息”(message)。在編譯階段,會將上面的代碼轉(zhuǎn)換成C語言函數(shù)調(diào)用,所調(diào)用的函數(shù)是消息傳遞機(jī)制中的核心函數(shù),叫作objc_megSend,其在objc/message.h文件下的定義如下:

voidobjc_msgSend(void/*idself,SELop,...*/)

objc_msgSend函數(shù)將消息接收者和方法名作為其基礎(chǔ)參數(shù)。其中,參數(shù)self代表消息接收者,參數(shù)SEL代表方法名(selector,又稱選擇器)。每個(gè)類中的方法列表(methodLists)類似于一張表格,其中的指針都會指向方法的實(shí)現(xiàn),而方法名是查表時(shí)所用的鍵。objc_msgSend函數(shù)正是通過這張表格來尋找應(yīng)該執(zhí)行的方法并跳轉(zhuǎn)至其實(shí)現(xiàn)的。

objc_msgSend函數(shù)會根據(jù)接收者和方法來調(diào)用適當(dāng)?shù)姆椒??;玖鞒倘缦拢?/p>

1)objc_msgSend函數(shù)通過isa指針在接收者所屬的類中搜尋方法緩存列表(cache)和方法列表,如果能找到與方法名相符合的方法,那么就跳轉(zhuǎn)至其實(shí)現(xiàn)代碼。

2)若是找不到,那么就會通過super_class指針沿著類的繼承體系繼續(xù)向上查找,如果能夠找到合適的方法,那么就會跳轉(zhuǎn)。

3)如果上面兩步都無法找到相符的方法,那么就會執(zhí)行消息轉(zhuǎn)發(fā)(messageforwarding)機(jī)制。

8.

如何使用UIView動畫自定義過渡動畫?正確答案:CATransition雖然是一種對那些不太好做平滑動畫屬性的強(qiáng)大工具,但是它的缺點(diǎn)也很明顯,那就是提供的動畫類型太少了。除此之外還可以使用UIView提供的過渡動畫API。

+(void)transitionWithView:duration:optiotis:animations:completion:;

+(void)transitionFromView:toView:duration:options:completion:;

和CATransition一樣,UIView提供的過渡動畫類型仍然很少,其中options參數(shù)可以指定如下常量。

typedefNS_ENUM(NSInteger,UIViewAnimationTransition){

UIViewAnimationTransitionNone,

UIViewAnimationTransitionFlipFromLett,

UIViewAnimationTransitionFlipFromRight,

UIViewAnimationTransitionCurlUp,

UIViewAnimationTransitionCurlDown,

};

在實(shí)際開發(fā)中,有時(shí)CATransition和UIView提供的過渡效果并不能滿足項(xiàng)目需求,這時(shí)就必須考慮實(shí)現(xiàn)自定義的過渡動畫了。

過渡動畫的基礎(chǔ)原則就是對原始圖層外觀截圖,然后添加一段動畫,平滑過渡到圖層改變之后那個(gè)截圖的效果。CALayer的renderInContext:方法可以將當(dāng)前圖層內(nèi)容繪制成圖片,然后在視圖中顯示出來。如果將這個(gè)截屏視圖置于原始視圖之上,那么就可以遮住真實(shí)視圖的所有變化,于是就能通過簡單的UIView動畫API創(chuàng)建過渡效果。對當(dāng)前視圖狀態(tài)截圖,然后在改變背景圖片的時(shí)候?qū)貓D快速轉(zhuǎn)動并且淡出,示例代碼如下:

-(void)startCustomTransitionAnimation{

/*獲取截圖*/

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size,YES,0);

[self.view.layerrenderInContext:UIGraphicsGetCurrentContext()];

UIImage*coverImage=UIGraphicsGetImageFromCurrentImageContext();

/*將截圖添加到主視圖*/

UIImageView*coverImageView=[[UIImageViewalloc]initWithImage:coverImage];

coverImageView.frame=self.view.bounds;

[self.viewaddSubview:coverImageView];

/*更換背景圖片*/

self.view.layer.contents=(id)[UIImageimageNamed:@"2"].CGImage;

/*添加動畫*/

[UIViewanimateWithDuration:1animations:^{

CGAffineTransformtransform=CGAffineTransformMakeScale(0.01,0.01);

transform=CGAffineTransformRotate(transfoma,M_PI_2);

coverImageView.alpha=0;

coverImageView.transform=transform;

}completion:^(BOOLfinished){

[coverImageViewremoveFromSuperview];

}];

}

效果如圖所示。

動畫過渡效果

9.

在ARC環(huán)境下,是否需要使用copy關(guān)鍵字來修飾block?正確答案:先要明確的是,block其實(shí)包含兩個(gè)組成部分,一部分是block所執(zhí)行的代碼,這一部分在編譯的時(shí)候已經(jīng)確定;另一部分是block執(zhí)行時(shí)所需要的外部變量值的數(shù)據(jù)結(jié)構(gòu)。根據(jù)block在內(nèi)存中的位置,系統(tǒng)將block分為3類。

1)NSGlobalBlock:該類型的block類似函數(shù),內(nèi)存地址位于內(nèi)存全局區(qū)。只要block沒有對作用域中局部變量進(jìn)行引用,此block會被系統(tǒng)設(shè)置為該類型。示例代碼如下:

-(void)test{

void(^gBlock1)(int,int)=^(inta,intb){

NSLog(@"a+b=%d",a+b);

};

NSLog(@"%@",gBlock1);

}

以上代碼的輸出結(jié)果是:<__NSGlobalBlock__:0x1025e8110>

事實(shí)上,對于NSGlobalBlock類型的block,無需做更多的處理,不需要使用retain和copy進(jìn)行修飾。即使使用了copy,系統(tǒng)也不會改變block的內(nèi)存地址,操作是無效的。

2)NSStackBlock:該類型的block內(nèi)存位于棧,其生命周期由函數(shù)決定,函數(shù)返回后block將無效。

在MRC環(huán)境下,若block內(nèi)部引用了局部變量,此block就會被系統(tǒng)設(shè)置為該類型。對于NSStackBlock類型的block,使用retain和release操作都是無效的,必須調(diào)用Block_copy()方法,或者使用copy進(jìn)行修飾,其作用就是將block的內(nèi)存從棧轉(zhuǎn)移到堆,此時(shí)block就會轉(zhuǎn)變?yōu)镹SMallocBlock類型,這也是一直使用copy修飾block的原因。

在ARC環(huán)境下,若block內(nèi)部引用了局部變量,系統(tǒng)默認(rèn)使用了copy對block進(jìn)行修飾,使其變成NSMallocBlock類型。所以在ARC環(huán)境下,不需要手動使用copy關(guān)鍵字來修飾block。

3)NSMallocBlock:當(dāng)對NSStackBlock類型的block進(jìn)行copy操作后,block就會轉(zhuǎn)為此類型。在MRC環(huán)境下,可以使用retain、release等方法手動管理此類型block的生命周期。在ARC環(huán)境下,系統(tǒng)會幫助管理此類型block的生命周期。

10.

什么是SpriteKit和SceneKit正確答案:SpriteKit和SceneKit是蘋果公司提供的分別用于開發(fā)2D游戲和3D游戲的框架。

目前蘋果公司提供的游戲引擎有3個(gè):用于2D游戲開發(fā)的SpriteKit框架、用于3D游戲開發(fā)的SceneKit框架和底層的游戲圖形庫Metal。這3個(gè)框架引擎一起重新定義了基于iOS設(shè)備強(qiáng)大GPU的移動游戲開發(fā)。另外,iOS平臺常用的熱門第三方2D游戲引擎為Cocos引擎,它包括Cocos2d-iphone和Cocos2d-x。各種游戲引擎的簡介見下表。

11.

一個(gè)tableView是否可以關(guān)聯(lián)兩個(gè)不同的datasource數(shù)據(jù)源?正確答案:多個(gè)數(shù)據(jù)源是完全可以的,問題的重點(diǎn)是如何關(guān)聯(lián),因?yàn)閷?shù)據(jù)源(Model)和tableView視圖的對接工作是程序員完成的,所以數(shù)據(jù)源的多少沒有根本影響。處理上可以分開依次對接,也可以通過數(shù)據(jù)的集合操作先將數(shù)據(jù)整理合并成一個(gè)數(shù)據(jù)源,然后對接。

例如,一個(gè)表格中的每個(gè)cell顯示的是一個(gè)人的基本信息,為了簡單這里假設(shè)只有一個(gè)頭像和I一個(gè)姓名。假設(shè)有兩個(gè)數(shù)據(jù)源,一個(gè)數(shù)據(jù)源是頭像的url數(shù)組;另一個(gè)是姓名的字符串?dāng)?shù)組,對接時(shí)完全可以分開在cell數(shù)據(jù)回調(diào)中對接,也可以將兩個(gè)數(shù)組合并然后對接。

合并數(shù)據(jù)用到的數(shù)據(jù)模型:

@interfaceModel:NSObject

@property(nonatomic,copy)NSString*name;

//姓名

@property(nonatomic,copy)NSString*url;

//圖片

@end

數(shù)據(jù)源緩沖器:

/*數(shù)據(jù)源*/

@property(nonatomic,strong)NSArray*nmne_datasource;

@property(nonatomic,strong)NSArray*url_datasource;

@property(nonatomic,strong)NSMutableArray*datasource;

處理多數(shù)據(jù)源:

/*請求數(shù)據(jù)*/

-(void)request{

/*姓名數(shù)據(jù)源*/

_name_datasource=@[@"張三",@"李四",@"小明",@"小李"];

_url_datasource=@[@"male",@"male",@"male",@"male"];

/*合并數(shù)據(jù)源*/

for(inti;i<_name_datasource.count;i++){

Model*model=[[Modelalloc]init];

=_name_datasource[i];

model.url=_url_datasource[i];

[_datasourceaddObject:model];

}

}

數(shù)據(jù)對接:

/*cell數(shù)據(jù)回調(diào)*/

-(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath{

staticNSString*identifier=@"identifier";

/*自制cell組件*/

AccountCell*cell=[[AccountCellalloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:identifier];

/**多數(shù)據(jù)源分開對接:**/

/*頭像*/

[cell.avatarsetImage:[UIImageimageNamed:_url_datasource[indexPath.row]];

/*姓名*/

.text=_name_datasource[indexPath.row];

/*或者:*/

/**數(shù)據(jù)源合并后對接**/

/*取出對應(yīng)數(shù)據(jù)模型*/

Model*model=_datasource[indexPath.row];

/*頭像*/

[cell.avatarsetImage:[UIImageimageNamed:model.url]];

/*姓名*/

.text=;

returncell;

}

12.

iOS中如何實(shí)現(xiàn)為UIImageView添加圓角?正確答案:圓角指按照一定圓角半徑平滑矩形視圖的4個(gè)角的效果,如圖所示。

圓角效果

按照背后的渲染方式,實(shí)現(xiàn)UIView及其子類的圓角效果有兩種方法:一種是直接設(shè)置layer的圓角屬性,為“離屏渲染”;另一種是自定義圓角繪制方法,實(shí)現(xiàn)“當(dāng)前屏幕渲染”。

當(dāng)前屏幕渲染(On-screenRendering)指GPU直接在當(dāng)前顯示的屏幕緩沖區(qū)中進(jìn)行圖形渲染,不需要提前另開緩沖區(qū)也就不需要緩沖區(qū)的切換,因此性能較高。

離屏渲染(Off-screenRendeiing):簡單來說就是提前另開一個(gè)緩沖區(qū)進(jìn)行圖形渲染,由于顯示需要和當(dāng)前屏幕緩沖區(qū)進(jìn)行切換,所以很耗費(fèi)性能。通常圓角、遮罩、不透明度、陰影、漸變、光柵化和抗鋸齒等設(shè)置都會觸發(fā)離屏渲染。

(1)“離屏渲染”實(shí)現(xiàn)圓角

iOS中圓角效果實(shí)現(xiàn)的最簡單、最直接的方式是直接修改View的layer層參數(shù),這樣會觸發(fā)“離屏渲染”,性能不高。

/*設(shè)置圓角半徑*/

view.layer.cornerRadius=5;

/*將邊界以外的區(qū)域遮蓋住*/

view.layer.masksToBounds=YES;

(2)“當(dāng)前屏幕渲染”實(shí)現(xiàn)圓角

直接在當(dāng)前屏幕渲染繪制,提高性能。

為UIImage類擴(kuò)展一個(gè)實(shí)例方法:

/*On-screen-renderring繪制UIImage矩形圓角*/

-(UIImage*)imageWithComerRadius:(CGFloat)radiusofSize:(CGSize)size{

/*當(dāng)前UIImage的可見繪制區(qū)域*/

CGRectrect=(CGRect){0.f,0.f,size};

/*創(chuàng)建基于位圖的上下文*/

UIGraphicsBeginImageCoritextWithOptions(size,NO,UIScreen.mainScreen.scale);

/*在當(dāng)前位圖上下文添加圓角繪制路徑*/

CGContextAddPath(UIGraphicsGetCurrentContext0,[UIBezierPathbezierPathWithRoundedRect:rectcomerRadius:radius].CGPath);

/*當(dāng)前繪制路徑和原繪制路徑相交得到最終裁剪繪制路徑*/

CGContextClip(UIGraphicsGetCurrentContext());

/*繪制*/

[selfdrawInRect:rect];

/*取得裁剪后的image*/

UIImage*image=UIGraphicsGetImageFromCurrentImageContext();

/*關(guān)閉當(dāng)前位圖上下文*/

UIGraphicsEndImageContext();

returnimage;

}

使用時(shí),讓實(shí)例化的UIImage對象調(diào)用上面的實(shí)例方法即可。

UIImageView*imageView=[[UIImageViewalloc]initWithFrame:CGRectMake(10,10,100,100)];

/*創(chuàng)建并初始化UIImage*/

UIImage*image=[UIImageimageNamed:@"icon"];

/*添加圓角矩形*/

image=[imageimageWithComerRadius:50ofSize:imageView.frame.size];

[imageViewsetImage:image];

13.

什么是游標(biāo)?正確答案:在數(shù)據(jù)庫中,游標(biāo)提供了一種對從表中檢索出的數(shù)據(jù)進(jìn)行操作的靈活手段,它實(shí)際上是一種能從包括多條數(shù)據(jù)記錄的結(jié)果集中每次提取一條記錄的機(jī)制。

游標(biāo)總是與一條SQL選擇語句相關(guān)聯(lián),因?yàn)橛螛?biāo)由結(jié)果集(可以是零條、一條或由相關(guān)的選擇語句檢索出的多條記錄)和結(jié)果集中指向特定記錄的游標(biāo)位置組成。當(dāng)決定對結(jié)果集進(jìn)行處理時(shí),必須聲明一個(gè)指向該結(jié)果集的游標(biāo)。

游標(biāo)允許應(yīng)用程序?qū)Σ樵冋Z句SELECT返回的行結(jié)果集中每一行進(jìn)行相同或不同的操作,而不是一次對整個(gè)結(jié)果集進(jìn)行同一種操作:它還提供對基于游標(biāo)位置而對表中數(shù)據(jù)進(jìn)行刪除或更新的能力;而且,正是游標(biāo)把作為面向集合的數(shù)據(jù)庫管理系統(tǒng)和面向行的程序設(shè)計(jì)兩者聯(lián)系起來,使兩個(gè)數(shù)據(jù)處理方式能夠進(jìn)行溝通。

例如,聲明一個(gè)游標(biāo)student_cursor,用于訪問數(shù)據(jù)庫SCHOOL中的“學(xué)生基本信息表”,代碼如下:

LISESCHOOL

GO

DECLAREstudent_cursorCURSOR

FROMSELECT*FROM學(xué)生基本信息表

上述代碼中,聲明游標(biāo)時(shí),在SELECT語句中未使用WHERE子句,故此游標(biāo)返回的結(jié)果集是由“學(xué)生基本信息表”中的所有記錄構(gòu)成的。

在SELECT返回的行集合中,游標(biāo)不允許程序?qū)φ麄€(gè)行集合執(zhí)行相同的操作,但對每一行數(shù)據(jù)的操作不作要求。游標(biāo)的優(yōu)點(diǎn)有以下兩個(gè)方面的內(nèi)容:

1)在使用游標(biāo)的表中,對行提供刪除和更新的能力。

2)游標(biāo)將面向集合的數(shù)據(jù)庫管理系統(tǒng)和面向行的程序設(shè)計(jì)連接起來。

14.

如何使用KVO設(shè)置鍵值觀察依賴鍵?正確答案:很多情況下對象的屬性之間是相互關(guān)聯(lián)的,對象的一個(gè)屬性值依賴于另一個(gè)對象的一個(gè)或多個(gè)屬性,如果這些屬性中的任意一個(gè)值發(fā)生改變,那么被依賴屬性的值也會相應(yīng)發(fā)生改變。如果要觀察被依賴屬性值的變更,那么就需要使用KVO中的依賴鍵。實(shí)現(xiàn)KVO中的依賴鍵最重要的部分是設(shè)置依賴關(guān)系。示例代碼如下:

/*新建一個(gè)Student類,其中的preson屬性是Person類的實(shí)例*/

#import<Foundation/Foundation.h>

#import"Person.h"

@interfaceStudent:NSObject

@property(nonatomic,strong)NSString*infomation;

@property(nonatomic,strong)Person*preson;

@end

#import"Student.h"

@implementationStudent

@end

此時(shí)需要觀察Student類實(shí)例中infomation屬性值的變化,而infomation屬性的值依賴于preson屬性的值,那么如何確立這種依賴關(guān)系呢?開發(fā)者要手動實(shí)現(xiàn)infomation的setter和getter方法,還要實(shí)現(xiàn)keyPathsForValuesAffectingInfomation或者keyPathsForValuesAffectingValueForKey:方法,這兩個(gè)方法的作用都是用來告訴系統(tǒng)infomation屬性依賴于其他哪些屬性,而且這兩個(gè)方法都返回包含著依賴key-path的集合。在例子中,infomation屬性依賴于person中的age和name屬性,當(dāng)person中age或者name屬性發(fā)生改變時(shí),infomation的觀察者都會得到通知。在Student.m文件中添加如下代碼:

-(NSString*)infomation{

return[NSStringstringWithFormat:@"student_name=%@,student_age=%zd",,self.preson.age];

}

-(void)setInfomation:(NSString*)infomation{

NSArray*array=[infomationcomponentsSeparatedByString:@"#"];

[self.presonsetName:[arrayobjectAtIndex:0]];

[self.presonsetAge:[[arrayobjectAtIndex:1]integerValue]];

}

+(NSSet*)keyPathsForValuesAffectingInfomation{

NSSet*set=[NSSetsetWithObjects:@"person.age",@"",nil];

returnset;

}

現(xiàn)在已經(jīng)建立了依賴關(guān)系,還需要在控制器中添加觀察者和實(shí)現(xiàn)KVO的回調(diào)方法。

-(void)viewDidLoad{

astudent=[[Studentalloc]init];

astudent.person=[[Personalloc]init];

[astudentaddObserver:selfforKeyPath:@"infomation"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOldcontext:nil];

}

-(void)touchesBegan:(NSSet<UITouch*>*)toucheswithEvent:(UIEvent*)event{

astudent.person.age=20;

=@"jack";

}

-(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary<NSKeyValueChangeKey,id>*)changecontext:(void*)context{

if([keyPathisEqualToString:@"infornation"]){

NSLog(@"old_infomation:%@new_infomation:%@",change[NSKeyValueChangeOldKey],change[NSKeyValueChangeNewKey]);

}

}

程序的輸出結(jié)果如下:

2016-10-3119:01:19.34601[53615:2109010]old_infomation:student_name=(null),student_age=0new_infomation:student_name=(null),student_age=20

2016-10-3119:01:19.34601[53615:2109010]old_infomation:student_name=(null),student_age=20new_infomation:student_name=jack,student_age=20

當(dāng)分別為person屬性設(shè)置name和age時(shí),infomation的值都會發(fā)生變化,所以會打印兩次infomation的信息。當(dāng)然開發(fā)者仍然需要在恰當(dāng)?shù)臅r(shí)候解除觀察者,代碼如下:

-(void)dealloc{

[astudentremoveObserver:selfforKeyPath:@"infomation"];

}

15.

什么是CocoaPods?正確答案:1.CocoaPods的介紹

在iOS開發(fā)的過程中,為了避免重復(fù)開發(fā),往往會在項(xiàng)目中導(dǎo)入許多優(yōu)秀的開源工具,如網(wǎng)絡(luò)框架AFNetworking、異步加載圖片框架SDWebImage、下拉刷新框架MJRefresh等。添加框架最原始的方法就是將框架下載,然后手動拖動框架到自己的項(xiàng)目中再使用。這樣會帶來許多問題,例如:框架更新后需要重新下載再拖進(jìn)項(xiàng)目,框架之間代碼集成難度大很難解決框架之間的依賴問題,每次運(yùn)行都必須重新編譯導(dǎo)入的框架浪費(fèi)時(shí)間等。為了解決iOS第三方框架的管理的問題,提高開發(fā)效率,因此誕生了CocoaPods。CocoaPods(官網(wǎng)指南:,git:/CocoaPods/CocoaPods)是iOS上開源的依賴管理工具(DependencyManagerTool)或叫第三方框架管理工具,用來高效地管理iOS項(xiàng)目上的第三方框架。如果學(xué)習(xí)過Java語言,那么CocoaPods就和Java語言中Maven的功能類似;如果是Python,那么它就和pip的功能類似;如果是Nodejs,那么它就和npm功能類似。

2.CocoaPods的原理

CocoaPods的原理就是將所有的依賴庫都放到一個(gè)名為Pods的項(xiàng)目中,然后讓主項(xiàng)目依賴這個(gè)Pods項(xiàng)目,這樣就分離第三方依賴和主項(xiàng)目之間的依賴關(guān)系,所有第三方依賴都由Pods項(xiàng)目管理。Pods項(xiàng)目最終會被編譯為一個(gè)libPods.a的文件,主項(xiàng)目中引用這個(gè)libPods文件就能使用所有的第三方框架。

3.為什么要使用CocoaPods

當(dāng)我們需要使用第三方框架的時(shí)候,使用CocoaPods能夠快速地將開源框架的代碼集成到項(xiàng)目中,并自動添加動態(tài)庫和依賴框架,設(shè)置預(yù)編譯-ObjC,fno-objc-arc等,從而實(shí)現(xiàn)第三方框架的使用和更新管理。

4.CocoaPods的核心組件

(1)Podfile

配置文件,將需要用到的第三方框架寫入到這個(gè)文件中,并根據(jù)項(xiàng)目的需要標(biāo)注好版本號。

(2)Podfile.lock

版本控制文件,里面記錄了每個(gè)第三方框架的版本,防止項(xiàng)目中不同成員使用的第三方框架的版本號不一致。

(3).xcworkspace

工程的入口文件。

(4)Pods

里面存放了所有使用到的第三方框架。

16.

索引的優(yōu)缺點(diǎn)有哪些?正確答案:創(chuàng)建索引可以大大提高系統(tǒng)的性能??傮w來說,索引的優(yōu)點(diǎn)如下:

1)大大加快數(shù)據(jù)的檢索速度,這也是創(chuàng)建索引的最主要的原因。

2)索引可以加速表和表之間的連接。

3)索引在實(shí)現(xiàn)數(shù)據(jù)的參照完整性方面特別有意義,例如在外鍵列上創(chuàng)建索引可以有效地避免死鎖的發(fā)生,也可以防止當(dāng)更新父表主鍵時(shí),數(shù)據(jù)庫對子表的全表鎖定。

4)索引是減少磁盤I/O的有效手段之一。

5)當(dāng)使用分組(GROUPBY)和排序(ORDERBY)子句進(jìn)行數(shù)據(jù)檢索時(shí),可以顯著減少查詢中分組和排序的時(shí)間,大大加快數(shù)據(jù)的檢索速度。

6)創(chuàng)建唯一性索引,可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。

7)通過使用索引,可以在查詢的過程中,使用優(yōu)化隱藏器,提高系統(tǒng)的性能。

索引的缺點(diǎn)如下:

1)索引必須創(chuàng)建在表上,不能創(chuàng)建在視圖上。

2)創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,這種時(shí)間隨著數(shù)據(jù)量的增加而增加。

3)建立索引需要占用物理空間,如果要建立聚簇索引,那么需要的空間會很大。

4)當(dāng)對表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,系統(tǒng)必須要有額外的時(shí)間來同時(shí)對索引進(jìn)行更新維護(hù),以維持?jǐn)?shù)據(jù)和索引的一致性,所以索引降低了數(shù)據(jù)的維護(hù)速度。

索引的使用原則如下:

1)在大表上建立索引才有意義。

2)在WHERE子句或是連接條件經(jīng)常引用的列上建立索引。

3)索引的層次不要超過4層。

4)如果某屬性常作為最大值和最小值等聚集函數(shù)的參數(shù),那么考慮為該屬性建立索引。

5)表的主鍵、外鍵必須有索引。

6)創(chuàng)建了主鍵和唯一約束后會自動創(chuàng)建唯一索引。

7)經(jīng)常與其他表進(jìn)行連接的表,在連接字段上應(yīng)該建立索引。

8)經(jīng)常出現(xiàn)在WHERE子句中的字段,特別是大表的字段,應(yīng)該建立索引。

9)要索引的列經(jīng)常被查詢,并只返回表中的行的總數(shù)的一小部分。

10)對于那些查詢中很少涉及的列、重復(fù)值比較多的列盡量不要建立索引。

11)經(jīng)常出現(xiàn)在關(guān)鍵字ORDERBY、GROUPBY、DISTINCT后面的字段,最好建立索引。

12)索引應(yīng)該建在選擇性高的字段上。

13)索引應(yīng)該建在小字段上,對于大的文本字段甚至超長字段,不適合建索引。對于定義為CLOB、TEXT、IMAGE和BIT的數(shù)據(jù)類型的列不適合建立索引。

14)復(fù)合索引的建立需要進(jìn)行仔細(xì)分析。正確選擇復(fù)合索引中的前導(dǎo)列字段,一般是選擇性較好的字段。

15)如果單字段查詢很少甚至沒有,那么可以建立復(fù)合索引;否則考慮單字段索引。

16)如果復(fù)合索引中包含的字段經(jīng)常單獨(dú)出現(xiàn)在WHERE子句中,那么分解為多個(gè)單字段索引。

17)如果復(fù)合索引所包含的字段超過3個(gè),那么仔細(xì)考慮其必要性,考慮減少復(fù)合的字段。

18)如果既有單字段索引,又有這幾個(gè)字段上的復(fù)合索引,那么一般可以刪除復(fù)合索引。

19)頻繁進(jìn)行DML操作的表,不要建立太多的索引。

20)刪除無用的索引,避免對執(zhí)行計(jì)劃造成負(fù)面影響。

“水可載舟,亦可覆舟”,索引也一樣。索引有助于提高檢索性能,但過多或不當(dāng)?shù)乃饕矔?dǎo)致系統(tǒng)低效。不要認(rèn)為索引可以解決一切性能問題,否則就大錯(cuò)特錯(cuò)了。因?yàn)橛脩粼诒碇忻考舆M(jìn)一個(gè)索引,數(shù)據(jù)庫就要做更多的工作。過多的索引甚至?xí)?dǎo)致索引碎片。所以說,要建立一個(gè)“適當(dāng)”的索引體系,特別是對聚合索引的創(chuàng)建,更應(yīng)精益求精,這樣才能使數(shù)據(jù)庫得到高性能的發(fā)揮。所以,提高查詢效率是以消耗一定的系統(tǒng)資源為代價(jià)的,索引不能盲目地建立,這是考驗(yàn)數(shù)據(jù)庫管理員是否優(yōu)秀的一個(gè)很重要的指標(biāo)。

17.

#import與#include以及#import<>與#import""各有什么區(qū)別?正確答案:#import與#include都是用來引入頭文件的。與#include相比,Objective-C中#import的優(yōu)勢是不會引起重復(fù)包含,相當(dāng)于多了C/C++中#pragmaonce的作用,它可以保證頭文件只被編譯一次。

#import<>與#import""的區(qū)別和C/C++中#include<>與#include""的區(qū)別一樣:使用尖括號<>指用來引入系統(tǒng)的頭文件,而使用引號""指用來引入本地用戶頭文件。

18.

C和Objective-C如何混用?正確答案:Objective-C的編譯器主要可以識別以下幾種擴(kuò)展名的文件。

1).m文件:可以編寫Objective-C代碼或者C語言代碼。

2).cpp文件:C++文件,只能識別C++或者C語言代碼(C++兼容C)。

3).mm文件:主要用于編寫C++和Objective-C混編的代碼,可以同時(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)代碼混編,可以將兩種以上語言對接起來,從而實(shí)現(xiàn)跨平臺的對接通信。例如,可以使用C或C++語言與Objective-C對接,將Objective-C的原生iOS平臺接口封裝起來,供其他語言或平臺調(diào)用,即可實(shí)現(xiàn)跨平臺的通信。

19.

Objective-C有GC垃圾回收機(jī)制嗎?正確答案:垃圾回收(GarbageCollection,GC)簡單地說就是程序中及時(shí)處理廢棄不用的內(nèi)存對象的機(jī)制,防止內(nèi)存中廢棄對象堆積過多造成內(nèi)存泄漏。

Objective-C語言本身是支持垃圾回收機(jī)制的,但有平臺局限性,僅限于Mac桌面系統(tǒng)開發(fā)中,而在iPhone和iPad等蘋果移動終端設(shè)備中是不支持垃圾回收機(jī)制的。在移動設(shè)備開發(fā)中的內(nèi)存管理是采用手動引用計(jì)數(shù)(ManualRearenceCotrating,MRC)以及iOS5以后的自動引用計(jì)數(shù)(AutomaticRearenceCounting,ARC),本質(zhì)都是引用計(jì)數(shù)(RC),通過引用計(jì)數(shù)的方式來管理內(nèi)存的分配與釋放,從而防止內(nèi)存泄漏。

另外,引用計(jì)數(shù)和垃圾回收是有區(qū)別的。垃圾回收是宏觀的,對整體進(jìn)行內(nèi)存管理,雖然不同平臺垃圾回收機(jī)制不同,但基本原理都是一樣的:將所有對象看作一個(gè)集合,然后在GC循環(huán)中定時(shí)檢測活動對象和非活動對象,及時(shí)將用不到的非活動對象釋放掉以避免內(nèi)存

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(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

提交評論