版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
iOS程序員面試分類模擬30簡答題1.
虛擬地址、邏輯地址、線性地址、物理地址有什么區(qū)別?正確答案:虛擬地址指由程序產(chǎn)生的由段選擇符和段內(nèi)偏移地址組成的地址。這兩部分組成的地址并不能直接訪問物理內(nèi)(江南博哥)存,而是要通過分段地址的變換處理后才會對應(yīng)到相應(yīng)的物理內(nèi)存地址。
邏輯地址指由程序產(chǎn)生的段內(nèi)偏移地址。有時(shí)直接把邏輯地址當(dāng)成虛擬地址,兩者并沒有明確的界限。
線性地址指虛擬地址到物理地址變換之間的中間層,是處理器可尋址的內(nèi)存空間(稱為線性地址空間)中的地址。程序代碼會產(chǎn)生邏輯地址,或者說是段中的偏移地址,加上相應(yīng)段基址就生成了一個(gè)線性地址。如果啟用了分頁機(jī)制,那么線性地址可以經(jīng)過變換產(chǎn)生物理地址。若是沒有采用分頁機(jī)制,那么線性地址就是物理地址。物理地址指現(xiàn)在CPU外部地址總線上的尋址物理內(nèi)存的地址信號,是地址變換的最終結(jié)果。
虛擬地址到物理地址的轉(zhuǎn)化方法是與體系結(jié)構(gòu)相關(guān)的,一般有分段與分頁兩種方式。以x86CPU為例,分段、分頁都是支持的。內(nèi)存管理單元負(fù)責(zé)從虛擬地址到物理地址的轉(zhuǎn)化。邏輯地址是段標(biāo)識+段內(nèi)偏移量的形式,MMU通過查詢段表,可以把邏輯地址轉(zhuǎn)化為線性地址。如果CPU沒有開啟分頁功能,那么線性地址就是物理地址;如果CPU開啟了分頁功能,MMU還需要查詢頁表來將線性地址轉(zhuǎn)化為物理地址:邏輯地址(段表)→線性地址(頁表)→物理地址。
映射是一種多對一的關(guān)系,即不同的邏輯地址可以映射到同一個(gè)線性地址上;不同的線性地址也可以映射到同一個(gè)物理地址上。而且,同一個(gè)線性地址在發(fā)生換頁以后,也可能被重新裝載到另外一個(gè)物理地址上,所以這種多對一的映射關(guān)系也會隨時(shí)間發(fā)生變化。
2.
Foundation對象與CoreFoundation對象有什么區(qū)別?正確答案:Foundation對象是Objective-C對象,使用Objective-C語言實(shí)現(xiàn);而CoreFoundation對象是C對象,使用C語言實(shí)現(xiàn)。兩者之間可以通過__bridge、__bridge_transfer、__bridge_retained等關(guān)鍵字轉(zhuǎn)換(橋接)。
Foundation對象和CoreFoundation對象更重要的區(qū)別是ARC下的內(nèi)存管理問題。在非ARC下兩者都需要開發(fā)者手動管理內(nèi)存,沒有區(qū)別。但在ARC下,系統(tǒng)只會自動管理Foundation對象的釋放,而不支持對CoreFoundation對象的管理。因此,在ARC下兩者進(jìn)行轉(zhuǎn)換后,必須要確定轉(zhuǎn)換后的對象是由開發(fā)者手動管理,還是由ARC系統(tǒng)繼續(xù)管理,否則可能導(dǎo)致內(nèi)存泄漏問題。
下面以NSString對象(Foundation對象)和CFStringRef對象(CoreFoundation對象)為例,介紹兩者的轉(zhuǎn)換和內(nèi)存管理權(quán)移交問題。
1)在非ARC下,NSString對象和CFStringRef對象可以直接進(jìn)行強(qiáng)制轉(zhuǎn)換,都是手動管理內(nèi)存,無須關(guān)心內(nèi)存管理權(quán)的移交問題。
2)在ARC下,NSString對象和CFStringRef對象在相互轉(zhuǎn)換時(shí),需要選擇使用__bridge、__bridge_transfer和__bridge_retained來確定對象的管理權(quán)轉(zhuǎn)移問題,三者的作用語義分別如下:
①__bridge關(guān)鍵詞最常用,它的含義是不改變對象的管理權(quán)所有者,本來由ARC管理的Foundation對象,轉(zhuǎn)換成CoreFoundation對象后依然由ARC管理;本來由開發(fā)者手動管理的CoreFoundation對象轉(zhuǎn)換成Foundation對象后繼續(xù)由開發(fā)者手動管理。示例代碼如下:
/*ARC管理的Foundation對象*/
NSString*s1=@"string";
/*轉(zhuǎn)換后依然由ARC管理釋放*/
CFStringRefcfstring=(__bridgeCFStringRef)s1;
/*開發(fā)者手動管理的CoreFoundation對象*/
CFStringRefs2=CFStringCreateWithCString(NULL,"string",kCFStringEncodingASCII);
/*轉(zhuǎn)換后仍然需要開發(fā)者手動管理釋放*/
NSString*fstring=(__bridgeNSString*)s2;
②__bfidge_transfer用在將CoreFoundation對象轉(zhuǎn)換成Foundation對象時(shí),用于進(jìn)行內(nèi)存管理權(quán)的移交,即本來需由開發(fā)者手動管理釋放的CoreFoundation對象在轉(zhuǎn)換成Foundation對象后,交由ARC來管理對象的釋放,開發(fā)者不用再關(guān)心對象的釋放問題,因?yàn)椴粫l(fā)生內(nèi)存泄漏。示例代碼如下:
/*開發(fā)者手動管理的CoreFoundation對象*/
CFStringRefs2=CFStringCreateWithCString(NULL,"string",kCFStringEncodingASCII);
/*轉(zhuǎn)換后改由ARC管理對象的釋放,不用擔(dān)心內(nèi)存泄漏*/
NSString*fstring=(__bridge__transferNSString*)s2;
//NSString*fstring=(NSString*)CFBridgingRelease(s2);
//另一種等效寫法
③__bridge_retained用在將Foundation對象轉(zhuǎn)換成CoreFoundation對象時(shí),進(jìn)行ARC內(nèi)存管理權(quán)的剝奪,即本來由ARC管理的Foundation對象在轉(zhuǎn)換成CoreFoundation對象后,ARC不再繼續(xù)管理該對象,需要開發(fā)者自己進(jìn)行手動釋放該對象,否則會發(fā)生內(nèi)存泄漏。示例代碼如下:
/*ARC管理的Foundation對象*/
NSString*s1=@"string";
/*轉(zhuǎn)換后ARC不再繼續(xù)管理,需要手動釋放*/
CFStringRefcfstring=(__bridge__retainedCFStringRef)s1;
//CFStringRefcfstring=(CFStringRef)CFBridgingRetain(s1);
//另一種等效寫法
3.
delete與truncate命令有哪些區(qū)別?正確答案:相同點(diǎn):都可以用來刪除一個(gè)表中的數(shù)據(jù)。
不同點(diǎn):
1)truncate是一個(gè)數(shù)據(jù)定義語言(DataDefinitionLanguage,DDL),它會被隱式地提交,一旦執(zhí)行后將不能回滾。delete執(zhí)行的過程是每次從表中刪除一行數(shù)據(jù),同時(shí)將刪除的操作以日志的形式進(jìn)行保存,以便將來進(jìn)行回滾操作。
2)用delete操作后,被刪除的數(shù)據(jù)占用的存儲空間還在,還可以恢復(fù)。而用truncate操作刪除數(shù)據(jù),被刪除的數(shù)據(jù)會立即釋放所占有的存儲空間,被刪除的數(shù)據(jù)是不能被恢復(fù)的。
3)truncate的執(zhí)行速度比delete快。
4.
Nil、nil、NULL、NSNull有什么區(qū)別?正確答案:iOS中表示“空”的幾種關(guān)鍵詞的用法分別如下:NULL比較常用,一般指的是指向基本數(shù)據(jù)類型以及C類型的空指針,例如:int*var=NULL;nil也很常用,指的是指向Objective-C對象的空指針,例如:NSObject*obj=nil;Nil專門用于對Objective-C中的類賦空值,例如:Classclass=Nil;NSNull用于作為數(shù)組等集合類中的空元素,例如:NSArray*array=[NSArrayarrayWithObjects:[[NSObjectalloc]init],[NSNullnull],[[NSObjectalloc]init],[[NSObjectalloc]init],nil};
5.
Objective-C等同性中的字符串相等如何判斷?正確答案:有如下代碼:
NSString*firstUserName=@"nick";
NSString*secondUserName=@"nick";
if(firstUserName=secondUserName){
NSLog(@"areEqual");
}
else{
NSLog(@"areNotEqual");
}
上述程序會輸出“areEqual”。
看上去好像答案很明顯,其實(shí)不然。用“==”比較兩個(gè)指針相當(dāng)于檢查它們是否指向同一個(gè)對象(指針存儲的是對象的地址)。兩個(gè)指針只有指向同一個(gè)對象(兩個(gè)指針存儲相同的對象地址)時(shí)這兩個(gè)指針才相等。兩個(gè)指針指向的兩個(gè)對象的值相等,但不是同一個(gè)對象,那么這兩個(gè)指針還是不相等,所以這么分析上面的代碼應(yīng)該輸出“areNotEqual”。
在上面的代碼片中,firstUserName和secondUserName是指向兩個(gè)不同對象的指針,但為什么會輸出“areEqual”呢?是因?yàn)閕OS編譯器對string對象的引用做了優(yōu)化,也就是對字符串相同的對象做了復(fù)用而不是重新分配空間,所以上面代碼雖然是分別定義的兩個(gè)指針,但實(shí)際還是指向了同一個(gè)字符串對象,結(jié)果輸出“areEqual”。
6.
什么是消息推送?和NotificatiOil有什么區(qū)別?正確答案:消息推送指在App關(guān)閉時(shí)(不在前臺運(yùn)行時(shí)),仍然向用戶發(fā)送App的內(nèi)部消息。消息推送通知和Objective-C中的Notification通知機(jī)制不同,推送的消息是給用戶看的,也就是可見的,而通知機(jī)制是Objective-C語言中對象間通信的一種機(jī)制,基于觀察者模式,目的是觸發(fā)內(nèi)部事件,減小類之間的耦合度,對用戶是不可見的。
推送消息的可見形式主要有以下幾種:
1)鎖屏界面的橫幅推送消息。
2)頂部通知欄的橫幅推送消息。
3)應(yīng)用圖標(biāo)上的代表消息數(shù)量的紅色數(shù)字。
4)菜單頁面彈出框提示。
5)播放聲音提示。
下圖所示是iPhone中QQ推送的設(shè)置界面。
QQ推送的設(shè)置界面
下圖所示為iPhone中消息推送的形式。
iPhone中消息推送的形式
iOS開發(fā)中有兩種類型的消息推送:本地消息推送(LocalNotification)和遠(yuǎn)程消息推送(RemoteNotification)。
1)本地消息推送:本地消息推送很簡單,不需要聯(lián)網(wǎng),不需要服務(wù)器,由客戶端應(yīng)用直接發(fā)出推送消息,一般通過定時(shí)器在指定的時(shí)間進(jìn)行消息推送。
2)遠(yuǎn)程消息推送:遠(yuǎn)程消息推送過程略為復(fù)雜,需要客戶端從蘋果公司的APNS(ApplePushNotificationSerwices)服務(wù)器注冊獲得當(dāng)前用戶的設(shè)備令牌并發(fā)送給應(yīng)用的服務(wù)器,然后應(yīng)用的服務(wù)器才可以通過APNS服務(wù)器間接地向客戶端發(fā)送推送消息,期間難免會有延遲。
遠(yuǎn)程消息推送的具體流程如圖所示,開發(fā)中要和服務(wù)器合作共同完成。
遠(yuǎn)程消息推送流程圖
①App客戶端向APNS服務(wù)器發(fā)送設(shè)備的UDID和BundleIdentifier。
②APNS服務(wù)器對傳過來的信息加密生成一個(gè)deviceToken,并返回給客戶端。
③客戶端將當(dāng)前用戶的deviceToken發(fā)送給自己應(yīng)用的服務(wù)器。
④自己應(yīng)用的服務(wù)器將得到的deviceToken保存,需要的時(shí)候利用deviceToken向APNS服務(wù)器發(fā)送推送消息。
⑤APNS服務(wù)器接收到自己應(yīng)用的服務(wù)器的推送消息時(shí),驗(yàn)證傳過來的deviceToken,如果一致,那么將消息推送到客戶端。
7.
iOS中點(diǎn)與像素有什么關(guān)系?正確答案:1)點(diǎn)是iOS中標(biāo)準(zhǔn)的坐標(biāo)體系。它就是iOS中的虛擬像素,也被稱為邏輯像素。在標(biāo)準(zhǔn)設(shè)備中,一個(gè)點(diǎn)就是一個(gè)像素,但是在Ratina屏幕上,一個(gè)點(diǎn)等于2×2個(gè)像素。iOS用點(diǎn)作為屏幕的坐標(biāo)測算體系就是為了在Retina設(shè)備和普通設(shè)備上能有一致的視覺效果。
2)像素是圖片分辨率的尺寸單位。物理像素坐標(biāo)并不會用于屏幕布局,但是仍然和圖片有相對關(guān)系。UIImage是一個(gè)屏幕分辨率解決方法,它是用點(diǎn)來度量大小的。但是,一些底層的CGImage類型的圖片會使用像素,所以必須清楚在Retina設(shè)備和普通設(shè)備上,點(diǎn)和像素代表著不同的大小。
8.
objective-C的優(yōu)缺點(diǎn)有哪些?正確答案:Objective-C的優(yōu)缺點(diǎn)見表。Objective-C的優(yōu)缺點(diǎn)優(yōu)點(diǎn)缺點(diǎn)1)Objective-C是C語言的超集,在C語言的基礎(chǔ)上衍生了很多新的語言特性,封裝得很完善而且方便使用,大大降低了編程復(fù)雜度,因此開發(fā)中使用起來會感覺方便高效1)不支持命名空間(都是通過加一些像NS或者UI這樣的命名前綴來達(dá)到用命名空間防止命名沖突的作用,但這樣會使變量的命名更長)2)Category(類別)的使用,可以快速擴(kuò)展類的方法,同時(shí)使擴(kuò)展的功能模塊之間互不影響2)不支持運(yùn)算符重載3)Posing(扮演)特性,[ParentClassposeAs:[ChildrenClassclass]];該語言特性使得父類無須定義和初始化子類對象,即可通過父類扮演子類進(jìn)行操作3)不支持多重繼承(C++語言通過virtual關(guān)鍵字防止二義性的出現(xiàn),實(shí)現(xiàn)多重繼承)4)動態(tài)語言特性,動態(tài)類型、動態(tài)綁定和動態(tài)加載等,將類型確定、方法調(diào)用和資源加載等任務(wù)推遲到運(yùn)行時(shí),大大提高了編程靈活度4)使用動態(tài)運(yùn)行時(shí)類型,所有的方法都是通過消息傳遞機(jī)制方法調(diào)用,有其動態(tài)的優(yōu)勢,同時(shí)也使很多編譯時(shí)的優(yōu)化方法無法使用降低了性能,例如:內(nèi)聯(lián)方法等5)指針:Objective-C保留了C語言強(qiáng)大的指針特性
6)Objective-C與C/C++可在.mm文件中進(jìn)行混合編程,靈活度更高
9.
load和initialize的區(qū)別是什么?正確答案:相同點(diǎn):load和initialize都是為了給應(yīng)用運(yùn)行前提供運(yùn)行環(huán)境,并且每個(gè)類中不管是父類還是子類中最多只會調(diào)用一次。
不同點(diǎn):load方法在某個(gè)類文件被引用時(shí)調(diào)用,子類會自動調(diào)用父類的load方法;initialize是在類或者其子類的第一個(gè)方法被調(diào)用前調(diào)用。所以,如果類沒有被引用進(jìn)項(xiàng)目,那么就不會有l(wèi)oad調(diào)用,即使類文件被引用進(jìn)來,但是沒有使用,那么initialize也不會被調(diào)用。
10.
Objective-C中的屬性和實(shí)例變量有哪些區(qū)別?正確答案:從下面的代碼中可以很明顯地看出它們的區(qū)別:
@interfaceTest:NSObject{
/*實(shí)例變量*/
@private
NSString*major;
@public
intage;
}
/*屬性變量*/
@property(nonatomic,copy)NSString*name;
@end
Objective-C中的屬性主要是對傳統(tǒng)實(shí)例變量的封裝,類對象有一個(gè)屬性列表用來存放類的所有屬性。屬性和實(shí)例變量的區(qū)別主要有以下幾個(gè)方面的內(nèi)容:
1)實(shí)例變量的存放采用硬編碼,編譯后寫死,根據(jù)距起始地址的偏移量來訪問變量,不可再插入新變量,而屬性可以在運(yùn)行時(shí)動態(tài)添加刪除。
2)實(shí)例變量可以通過@prirate、@public和@protected等修飾詞來定義變量的作用域,限制變量的訪問權(quán)限,而屬性不可以。從設(shè)計(jì)角度,屬性主要是用來和外部類進(jìn)行訪問交互的,實(shí)例變量主要用于類內(nèi)部使用。
3)屬性可以通過三類屬性特質(zhì)分別來幫助內(nèi)存管理、多線程管理和讀寫控制,可以讓編譯器自動合成存取方法,而不用重復(fù)為每一個(gè)實(shí)例變量手寫存取方法造成代碼臃腫。
11.
tintColor的作用是什么?正確答案:tintColor是iOS7以后在UIView類中新增的一個(gè)屬性。tintColot具有傳遞性,一般用來改變應(yīng)用的主色調(diào),默認(rèn)為nil,表示用父視圖默認(rèn)的顏色進(jìn)行著色。
12.
id,NSObject,id<NSObject>的區(qū)別是什么?正確答案:NSObject修飾的對象肯定是NSObject對象,但id修飾的對象雖然肯定是Objective-C對象,但不一定是NSObject對象,id類型是一種運(yùn)行時(shí)的動態(tài)類型,編譯器不會對其進(jìn)行類型檢查。id<NSObject>修飾的對象也是一種動態(tài)類型對象,對象的類型在運(yùn)行時(shí)才確定,但編譯器知道它一定是遵守NSObject協(xié)議的。例如:id<NSObject>常用來定義delegate對象。
idfool;
//是Objective-C對象,但不是NSObject對象
NSObject*foo2;
//NSObject對象
id<NSObject>foo3;
//不是NSObject對象,但是遵守NSObject協(xié)議
13.
union和unionall有什么區(qū)別?正確答案:union在進(jìn)行表求并集后會去掉重復(fù)的元素,所以會對所產(chǎn)生的結(jié)果集進(jìn)行排序運(yùn)算,刪除重復(fù)的記錄再返回結(jié)果。
而unionall只是簡單地將兩個(gè)結(jié)果合并后就返回。因此,如果返回的兩個(gè)結(jié)果集中有重復(fù)的數(shù)據(jù),那么返回的結(jié)果集就會包含重復(fù)的數(shù)據(jù)了。
從上面的對比可以看出,在執(zhí)行查詢操作的時(shí)候,unionall要比union快很多。所以,如果可以確認(rèn)合并的兩個(gè)結(jié)果集中不包含重復(fù)的數(shù)據(jù),那么最好使用unionall。例如,有兩個(gè)學(xué)生表table1和table2。Table1C1C2112233Table2C1C2334411select*fromTable1unionselect*fromTable2的查詢結(jié)果為:C1C211223344select*fromTablelunionallselect*fromTable2的查詢結(jié)果為:C1C2112233334411
14.
如何解決masksToBounds離屏渲染帶來的性能損耗?正確答案:在開發(fā)中常通過CALayer的cornerRadius屬性來設(shè)置圖層的圓角曲率(如設(shè)置圓角圖片)。默認(rèn)情況下,cornerRadius只影響背景顏色而不影響背景圖片或子圖層。但當(dāng)將CALayer的masksToBounds設(shè)置為YES時(shí),圖層的內(nèi)容就會被截取。代碼如下:
imageView.layer.cornerRadius=10
imageView.layer.masksToBounds=YES
由于這樣處理的渲染機(jī)制是GPU在當(dāng)前屏幕緩沖區(qū)外新開辟的一個(gè)渲染緩沖區(qū)進(jìn)行工作,也就是所謂的離屏渲染,所以這會給應(yīng)用程序帶來額外的性能損耗。如果在某一時(shí)刻大量地使用這種方式設(shè)置圓角,那么就會觸發(fā)緩沖區(qū)頻繁合并和上下文之間的頻繁切換,這時(shí)應(yīng)用程序就有可能出現(xiàn)掉幀和卡頓。具體可以使用Xcode自帶的Instruments(工具)進(jìn)行檢測。
為了防止因離屏渲染而產(chǎn)生性能損耗,可以不使用CALayer的cornerRadius和masksToBounds屬性,而將處理圖片的權(quán)利交于CPU,雖然CPU對圖形的處理能力不及GPU,但設(shè)置圓角圖片的處理難度并不大,且代價(jià)遠(yuǎn)小于上下文切換。以下是實(shí)際開發(fā)中常用的兩種優(yōu)化方案:
1)使用CALayer提供的shouldRasterize屬性。shouldRasterize屬性是設(shè)置光柵化,可以使離屏渲染的結(jié)果緩存到內(nèi)存中存為位圖,當(dāng)下次使用的時(shí)候就可以直接使用內(nèi)存緩存,這樣就節(jié)省了一直離屏渲染的性能損耗。為了使用shouldRasterize屬性,還需要設(shè)置rasterizationScale屬性去匹配屏幕,以防止出現(xiàn)Retina屏幕像素化的問題。
imageView.layer.shouldRasterize=YES;
imageView.layer.msterizationScale=[UIScreenmainScreen].scale;
這種方法雖然能在一定程度上優(yōu)化性能,但是如果layer及sublayers經(jīng)常改變,那么它就會不停地渲染及設(shè)置緩存,在這種情況下還是很耗性能的。
2)通過CoreGraphics繪制出圓角圖片??梢允褂肬IKit中對CoreGraphics有一定封裝的應(yīng)用層類UIBezierPath,對圖片進(jìn)行重新剪切。示例代碼如下:
UIImageView*imageView=[[UIImageViewalloc]initWithFrame:CGRectMake(100,100,100,100)];
imageView.image=[UIImageimageNamed:@"1"];
/*開啟上下文
開始對imageView進(jìn)行畫圖*/
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,NO,1.0);
/*使用貝塞爾曲線畫出一個(gè)圓形圖*/
[[UIBezierPathbezierPathWithRoundedRect:imageView.bounds
cornerRadius:imageView.frame.size.width]addClip];
[imageViewdrawRect:imageView.bounds];
imageView.image=UIGraphicsGetImageFromCurrentImageContext();
/*關(guān)閉上下文結(jié)束畫圖*/
UIGraphicsEndImageContext();
[self.viewaddSubview:imageView];
15.
什么是Notification?什么時(shí)候用Delegate或Notification?正確答案:Notification(通知)是Cocoa框架中基于觀察者模式實(shí)現(xiàn)的用于一對多傳播消息的一種機(jī)制。項(xiàng)目中的對象將它們自己或者其他對象添加到通知的觀察者列表里(這個(gè)過程又叫通知注冊),其中項(xiàng)目中的所有通知都有一個(gè)唯一的字符串標(biāo)識作為通知名唯一確定每個(gè)通知,通知源也就是被觀察者可以創(chuàng)建通知對象并發(fā)送到通知中心,通知中心找出所有注冊該通知的對象(觀察者),并將從被觀察者那里收到通知以消息的方式發(fā)送給所有的觀察者們。被觀察者發(fā)送通知是一個(gè)同步過程,即發(fā)送者在通知中心成功將該發(fā)送者之前的消息發(fā)送給所有觀察者之前不可以再次發(fā)送通知。另外,通知觸發(fā)的代理方法都必須符合某個(gè)單一參數(shù)簽名約定,代理方法的參數(shù)是一個(gè)通知對象,參數(shù)里包含著通知名、被觀察者和一個(gè)包含其他額外信息的字典。
Delegate和Notification的主要區(qū)別在于前者是一對一的消息傳遞,而后者是一對多的,可以根據(jù)這個(gè)特點(diǎn)在使用中進(jìn)行選擇。另外在代理模式中,reciever(接收者)可以返回值給sender(發(fā)送者),實(shí)現(xiàn)一種回調(diào),而觀察者模式中觀察者不可以返回值給被觀察者,因此在需要實(shí)現(xiàn)回調(diào)時(shí)只能選擇代理模式。
16.
CocoaTouch的底層技術(shù)架構(gòu)是什么?正確答案:如圖所示,CocoaTouch的底層技術(shù)架構(gòu)主要分4層,每層負(fù)責(zé)的服務(wù)見下表。
CocoaTouch架構(gòu)圖CocoaTouch的4層架構(gòu)及其服務(wù)架構(gòu)層服務(wù)CocoaTouch框架層UI組件、觸摸處理和事件驅(qū)動、系統(tǒng)接口Media媒體層音頻視頻播放、動畫、2D和3D圖形CoreService核心服務(wù)層、底層特性、文件、網(wǎng)絡(luò)、位置服務(wù)等CoreOS系統(tǒng)層內(nèi)存管理、底層網(wǎng)絡(luò)、硬件管理
17.
Objective-C中數(shù)據(jù)類型的限定詞有哪些?正確答案:在Objective-C中,有如下幾個(gè)限定詞。
1.long
如果直接將限定詞long放到int聲明之前,那么其所聲明的整型變量在某些計(jì)算上將具有拓展的值域,也就是說該整型變量的儲值范圍將變大。一個(gè)longint聲明的例子為:
longintprice;
longint類型的常量值可通過在整型常量末尾添加字母L(不區(qū)分大小寫)來完成。單數(shù)字和L之間不允許使用空格。一個(gè)longint類型常量的例子為:
longintprice=123456789L;
另外,要用NSLog打印longint的值,使用字母1作為修飾并放在整型格式符號i、o和x之前。例如“%lx”表示十六進(jìn)制格式顯示值。
同理,也可以將long限定詞放到double聲明之前,如:
longdoublelongDouble;
longdouble常量可寫成其尾部帶有字母l或L的浮點(diǎn)常量,例如:1.234e+7L。要顯示longdouble的值,需要使用修飾符L。因此,%Lf用浮點(diǎn)計(jì)數(shù)法顯示longdouble的值,%Le用科學(xué)計(jì)數(shù)法顯示同樣的值,而%Lg將告訴NSLog在%Lf和%Le之間任選一個(gè)使用。
2.longlong
結(jié)合上面所描述的,longlong限定詞同樣具有拓展存儲數(shù)據(jù)值的范圍和精度的作用。可以用如下形式使用:
longlongintmaxIntStorage;
NSLog字符串不使用單個(gè)字母l,而使用兩個(gè)l來顯示longlong的整數(shù),例如“%lli”。
3.short
使用short限定詞修飾的變量主要用來存儲比較小的整數(shù)。主要的好處是在應(yīng)用開發(fā)中能夠節(jié)約內(nèi)存空間,在一般情況下,shortint占用的內(nèi)存空間是常規(guī)int變量所占空間的一半。
4.unsigned
顧名思義,unsigned這個(gè)限定詞當(dāng)放在int變量之前,就是向編譯器聲明所修飾的整數(shù)變量只用于存儲正整數(shù)。通過限定了整型變量的使用,讓它專門用于存儲正整數(shù),可以擴(kuò)展整型變量的范圍。一般unsignedint可簡寫為uint。例如:
uintunsignedIntNumber;
其等價(jià)于:
unsignedintunsignedIntNumber;
18.
如何使用CAShapeLayer繪制圖層?正確答案:CAShapeLayer是一個(gè)通過矢量圖形來進(jìn)行繪制的圖層子類。開發(fā)者通過指定諸如顏色和線寬等屬性,用CGPath來定義指定形狀的圖形,最后CAShapeLayer對象就會自動渲染出來了。與直接使用CoreGraphics在原始的CALayer對象中繪制的方式相比,使用CAShapeLayer有以下優(yōu)點(diǎn):
1)渲染速度更快。CAShapeLayer使用了硬件加速的方式繪制圖形,繪制速度比用CoreGraphics快很多。
2)內(nèi)存使用更加高效。普通的CALayer對象需要?jiǎng)?chuàng)建一個(gè)寄宿圖,而CAShapeLayer不需要,這樣就節(jié)約了內(nèi)存。
3)不會被邊界圖層裁剪掉。一個(gè)CAShapeLayer可以在圖層邊界繪制。CAShapeLayer的圖層路徑不會像在使用CoreGraphics的普通CALayer一樣被裁剪掉。
通常通過指定CAShapeLayer對象的path屬性來繪制圖層。代碼如下:
@property(nullable)CGPathRefpath;
此外還可以通過一些屬性來描繪形狀的線條,例如lineWidth屬性用于設(shè)置線寬,lineCap屬性用于描繪線條結(jié)尾的樣子,但是在圖層層面只有一次機(jī)會設(shè)置這些屬性。如果想用不同顏色或風(fēng)格來繪制多個(gè)形狀,那么就不得不為每個(gè)形狀準(zhǔn)備一個(gè)圖層。下面示例使用CAShapeLayer渲染一個(gè)簡單的多邊形,由于CAShapeLayer對象的path屬性是CGPathRef類型,所以很容易使用UIBezierPath類幫助創(chuàng)建圖層路徑,這樣就不需要人工釋放CGPath了。代碼如下:
/*創(chuàng)建一個(gè)CAShapeLayer對象*/
CAShapeLayer*shaperLayer=[CAShapeLayerlayer];
/*設(shè)置線寬*/
shaperLayer.lineWidth=2;
shaperLayer.lineCap=kCALineCapRound;
shaperLayer.lineJoin=kCALineJoinRound;
/*設(shè)置描邊顏色*/
shaperLayer.strokeColor=[UIColorredColor].CGColor;
/*設(shè)置填充顏色*/
shaperLayer.fillColor=[UIColorwhiteColor].CGColor;
/*創(chuàng)建一個(gè)UIBezierPath對象*/
UIBezierPath*bezierPath=[UIBezierPathbezierPath];
[bezierPathmoveToPoint:CGPointMake(160,100)];
[bezierPathaddLineToPoint:CGPointMake(100,160)];
[bezierPathaddLineToPoint:CGPointMake(100,220)];
[bezierPathaddLineToPoint:CGPointMake(160,280)];
[bezierPathaddLineToPoint:CGPointMake(220,220);
[bezierPathaddLineToPoint:CGPointMake(220;160)];
[bezierPathclosePath];
/*繪制*/
shaperLayer.path=bezierPath.CGPath;
[self.view.layeraddSublayer:shaperLayer];
代碼執(zhí)行效果如圖所示。
CAShapeLayer繪制的路徑圖
19.
MethodSwizzling的應(yīng)用場景有哪些?正確答案:MethodSwizzling主要用于在運(yùn)行時(shí)對編譯器編譯好的方法再次進(jìn)行編輯,應(yī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)對調(diào),以及將兩個(gè)類方法的實(shí)現(xiàn)對調(diào)。注意運(yùn)行時(shí)代碼寫在類的load方法內(nèi),該方法只會在該類第一次加載時(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方法有且只有一次會被調(diào)用)*/
+(void)load{
/*1.獲取當(dāng)前類名*/
Classclass=[selfclass];
/*2.獲取方法名(選擇器)*/
SELselInsMethodl=@selector(instanceMethod1);
SELselInsMethod2=@selector(instanceMethod2);
SELselClassMethod1=@selector(classMethod1);
SELselClassMethod2=@selector(classMethod2);
/*3.根據(jù)方法名獲取方法對象*/
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);
}
測試代碼:
#import"ViewController.h"
#import"Test.h"
@implementationViewController
-(void)viewDidLoad{
[superviewDidLoad];
/*測試類方法調(diào)用*/
[TestclassMethod1];
[TestclassMethod2];
Test*test=[[Testalloc]init];
/*測試實(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,selCl
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 口罩產(chǎn)品知識培訓(xùn)課件
- 2025廣東東莞市大灣區(qū)大學(xué)行政崗位招聘1人備考題庫帶答案詳解
- 2026廣東廣外附屬科學(xué)城實(shí)驗(yàn)學(xué)校小學(xué)語文教師招聘2人備考題庫及一套答案詳解
- 2026年福建莆田第二中編外合同教師招聘12人備考題庫及答案詳解(新)
- 2026北京協(xié)和醫(yī)院心內(nèi)科合同制科研助理招聘備考題庫參考答案詳解
- 足浴技術(shù)培訓(xùn)課件
- 2026中建玖玥城市運(yùn)營公司招聘2人備考題庫(北京)及一套完整答案詳解
- 物品清點(diǎn)的安全管理措施試題(含答案)
- 2025年漯河市人力資源和社會保障局所屬事業(yè)單位人才引進(jìn)1名備考題庫及一套參考答案詳解
- 柳州市三支一扶考試真題2025
- 關(guān)于若干歷史問題的決議(1945年)
- 畢業(yè)論文8000字【6篇】
- 隨訪管理系統(tǒng)功能參數(shù)
- GB/T 5039-2022杉原條
- SH/T 0362-1996抗氨汽輪機(jī)油
- GB/T 23280-2009開式壓力機(jī)精度
- GB/T 17213.4-2015工業(yè)過程控制閥第4部分:檢驗(yàn)和例行試驗(yàn)
- FZ/T 73009-2021山羊絨針織品
- 珠海局B級安檢員資格考試試題及答案
- GB∕T 5900.2-2022 機(jī)床 主軸端部與卡盤連接尺寸 第2部分:凸輪鎖緊型
- 2011-2015廣汽豐田凱美瑞維修手冊wdl
評論
0/150
提交評論