版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
iOS程序員面試分類模擬29簡答題1.
如何使用runtime動態(tài)添加一個類?正確答案:runtime之所以非常強大,很關(guān)鍵的一點就是它能夠動態(tài)地創(chuàng)建一個全新的類或?qū)ο?。在runtime.h文件中(江南博哥)可以查到動態(tài)創(chuàng)建一個類所涉及的所有函數(shù)。
/*創(chuàng)建一個新類或元類*/
objc_allocateClassPair(Classsuperclass,constchar*name,size_textraBytes)
/*注冊一個通過objc_allocateClassPair方法創(chuàng)建的類*/
objc_registerClassPair(Classcls)
/*銷毀一個類及其元類*/
objc_disposeClassPair(Classcls)
上面3個函數(shù)的作用見表。動態(tài)創(chuàng)建類所涉及的3個函數(shù)函數(shù)名作用objc_allocateClassPair函數(shù)它的作用是創(chuàng)建一個新類或元類。如果開發(fā)者想讓這個類成為基類,那么參數(shù)superclass指定為nil。參數(shù)extraBytes是分配給類和元類對象尾部的索引ivars的字節(jié)數(shù),通常指定為0objc_registerClassPair函數(shù)當(dāng)創(chuàng)建完新類后,需要調(diào)用這個方法來注冊這個類,之后這個類才可以在程序中使用objc_disposeClassPair函數(shù)用于銷毀一個類及其元類。需要注意的一點是,如果程序運行中還存在類或其子類的實例,那么就不能調(diào)用該方法
那么,如何運用上述3個函數(shù)動態(tài)地添加一個類呢?示例代碼如下:
/*創(chuàng)建一個新類myClass*/
ClassmyClass=objc_allocateClassPair([NSObjectclass],"myClass",0);
/*添加ivar*/
//@encode(aType):返回該類型的C字符串
class_addIvar(myClass,"_address",sizeof(NSString*),log2(sizeof(NSString*)),@encode(NSString*));
class_addIvar(myClass,"_age",sizeof(NSUInteger),log2(sizeof(NSUInteger)),@encode(NSUInteger));
/*注冊類*/
objc_registerClassPair(myClass);
/*創(chuàng)建實例*/
idobject=[[myClassalloc]init];
/*為ivar設(shè)置值*/
[objectsetValue:@"china"forKey:@"address"];
[objectsetValue:@20forKey:@"age"];
NSLog(@"address=%@,age=%@",[objectvalueForKey:@"address"],[objectvalueForKey:@"age"]);
/*當(dāng)類或者它的子類的實例還存在,則不能調(diào)用objc_disposeClassPair方法*/
object=nil;
/*銷毀*/
objc_disposeClassPair(myClass);
程序的打印結(jié)果如下:
2016-11-0219:32:39.61501[67782:2681508]address=china,age=20
這樣就通過運行時動態(tài)創(chuàng)建了一個繼承自NSObject的myClass類,并為這個新類添加了address和age兩個成員變量。特別需要注意的是,添加成員變量的方法class_addIva必須要在objc_allocateClassPair和objc_registerClassPair之間調(diào)用才行,這里涉及Objective-C中類的成員變量的偏移量,如果在類注冊之后再調(diào)用class_addIva方法,那么會破壞原來類成員變量正確的偏移量,導(dǎo)致的后果就是會獲取到錯誤的成員變量。
2.
一二三四范式有什么區(qū)別?正確答案:在設(shè)計與操作維護數(shù)據(jù)庫時,最關(guān)鍵的問題就是要確保數(shù)據(jù)正確地分布到數(shù)據(jù)庫的表中。使用正確的數(shù)據(jù)結(jié)構(gòu),不僅有助于對數(shù)據(jù)庫進行相應(yīng)的存取操作,還可以極大地簡化應(yīng)用程序的其他內(nèi)容(查詢、窗體、報表、代碼等),正確地進行表的設(shè)計成為“數(shù)據(jù)庫規(guī)范化”,它的目的就是減少數(shù)據(jù)庫中的數(shù)據(jù)冗余,從而增加數(shù)據(jù)的一致性。
規(guī)范化是在識別數(shù)據(jù)庫中的數(shù)據(jù)元素、關(guān)系,以及定義所需的表和各表中的項目這些初始工作之后的一個細化的過程。常見的范式有1NF、2NF、3NF、BCNF及4NF。
1NF,第一范式。它指數(shù)據(jù)庫表的每一列都是不可分割的基本數(shù)據(jù)項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重復(fù)的屬性。如果出現(xiàn)重復(fù)的屬性,那么就可能需要定義一個新的實體,新的實體由重復(fù)的屬性構(gòu)成,新實體與原實體之間為一對多關(guān)系。第一范式的模式要求屬性值不可再分裂成更小部分,即屬性項不能是屬性組合或由組屬性組成。簡而言之,第一范式就是無重復(fù)的列。例如,由“職工號”“姓名”“電話號碼”組成的表(一個人可能有一個辦公電話和一個移動電話),這時將其規(guī)范化為1NF可以將電話號碼分為“辦公電話”和“移動電話”兩個屬性,即職工(職工號、姓名、辦公電話、移動電話)。
2NF,第二范式。第二范式是在第一范式的基礎(chǔ)上建立起來的,即滿足第二范式必須先滿足第一范式。第二范式要求數(shù)據(jù)庫表中的每個實例或行必須可以被唯一地區(qū)分。為實現(xiàn)區(qū)分通常需要為表加上一個列,以存儲各個實例的唯一標(biāo)識。如果關(guān)系模式(R)為第一范式,并且R中每一個非主屬性完全函數(shù)依賴于R的某個候選鍵,則稱R為第二范式模式。(如果A是R的候選鍵的一個屬性,則稱A是R的主屬性,否則稱A是R的非主屬性。)例如,在選課關(guān)系表(學(xué)號、課程號、成績、學(xué)分),關(guān)鍵字為組合關(guān)鍵字(學(xué)號、課程號),由于非主屬性學(xué)分僅依賴于課程號,對關(guān)鍵字(學(xué)號、課程號)只是部分依賴,而不是完全依賴,所以此種方式導(dǎo)致數(shù)據(jù)冗余及更新異常等問題,解決辦法是將其分為兩個關(guān)系模式:學(xué)生表(學(xué)號、課程號、分數(shù))和課程表(課程號、學(xué)分),新關(guān)系通過學(xué)生表中的外關(guān)鍵字課程號聯(lián)系,在需要時進行連接。
3NF,第三范式。如果R是第二范式,且每個非主屬性都不傳遞依賴于R的候選鍵,則稱R是第三范式的模式。例如學(xué)生表(學(xué)號、姓名、課程號、成績),其中學(xué)生姓名無重名,所以該表有兩個候選鍵(學(xué)號、課程號)和(姓名、課程號),則存在函數(shù)依賴:學(xué)號→姓名,(學(xué)號、課程號)→成績,(姓名、課程號)→成績,唯一的非主屬性成績對候選鍵不存在部分依賴,也不存在傳遞依賴,所以屬于第三范式。
BCNF。它構(gòu)建在第三范式的基礎(chǔ)上,如果R是第一范式,且每個屬性都不傳遞依賴于R的候選鍵,那么稱R為BCNF的模式。假設(shè)倉庫管理關(guān)系表(倉庫號、存儲物品號、管理員號、數(shù)量),滿足一個管理員只在一個倉庫工作;一個倉庫可以存儲多種物品。則存在如下關(guān)系:
(倉庫號、存儲物品號)→(管理員號、數(shù)量)
(管理員號、存儲物品號)→(倉庫號、數(shù)量)
所以,(倉庫號、存儲物品號)和(管理員號、存儲物品號)都是倉庫管理關(guān)系表的候選鍵,表中的唯一非關(guān)鍵字段為數(shù)量,它是符合第三范式的。但是,由于存在如下決定關(guān)系:
(倉庫號)→(管理員號)
(管理員號)→(倉庫號)
即存在關(guān)鍵字段決定關(guān)鍵字段的情況,所以其不符合BCNF范式。把倉庫管理關(guān)系表分解為兩個關(guān)系表:倉庫管理表(倉庫號、管理員號)和倉庫表(倉庫號、存儲物品號、數(shù)量),這樣的數(shù)據(jù)庫表是符合BCNF范式的,消除了刪除異常、插入異常和更新異常。
4NF,第四范式。設(shè)R是一個關(guān)系模式,D是R上的多值依賴集合。如果D中成立非平凡多值依賴X→Y時,X必是R的超鍵,那么稱R是第四范式的模式。例如,職工表(職工編號、職工孩子姓名、職工選修課程),在這個表中同一個職工也可能會有多個職工孩子姓名,同樣,同一個職工也可能會有多個職工選修課程,即這里存在著多值事實,不符合第四范式。如果要符合第四范式,那么只需要將上表分為兩個表,使它們只有一個多值事實,例如職工表一(職工編號、職工孩子姓名),職工表二(職工編號、職工選修課程),兩個表都只有一個多值事實,所以符合第四范式。
下圖為各范式關(guān)系圖。
各范式關(guān)系圖
3.
為什么iOS中提供UIView和CALayer這兩個平行的層級結(jié)構(gòu)呢?正確答案:iOS中提供UIView和CALayer這兩個平行層級結(jié)構(gòu)主要是為了做到職責(zé)分離,實現(xiàn)視圖的繪制、顯示和布局解耦,避免很多重復(fù)的代碼。在iOS和MacOS兩個平臺上,事件和用戶交互有很多地方并不相同,畢竟基于多點觸控的用戶界面和基于鼠標(biāo)鍵盤有著本質(zhì)的區(qū)別,這就是為什么iOS有UIKit和UIView,但是MacOS有Appkit和NSView的原因。它們功能雖然相似,但是在實現(xiàn)上有著顯著的區(qū)別。創(chuàng)建兩個層次結(jié)構(gòu)就能夠在iOS與MacOS之間共享代碼,從而使得開發(fā)更加便捷。
4.
contentsScale屬性有什么作用?正確答案:圖層的contentsScale屬性屬于支持高分辨率屏幕(如Retina屏幕)機制的一部分,它定義了圖層content中圖像的像素尺寸與視圖大小的比例。它也被用來判斷在繪制圖層時允許為content屬性創(chuàng)建的空間大小,以及需要顯示的圖片的拉伸度。
默認情況下,contentsScale的值是1.0,也就是說圖層的繪制系統(tǒng)將會以每個點對應(yīng)一個像素來繪制圖片。如果將其設(shè)置為2.0,那么會以每個點對應(yīng)兩個像素來繪制圖片,此即所謂的Retina屏幕。
在開發(fā)中,有時會直接為圖層的content設(shè)置圖片,這時可以設(shè)置contentsScale為合適的值,以防止圖片在Retina屏幕上顯示不正確(像素化或模糊),代碼如下:
layer.contentsScale=[UIScreenmainScreen].scale;
5.
分別寫一個setter方法用于完成非ARC下的@property(nonatomic,retain)NSString*name和@property(nonatomic,copy)NSString*name。正確答案:第一種情況,retain是指針變量name對新賦值對象的強引用,相當(dāng)于ARC下的strong,因此對name指針變量set新值時要先將新賦值對象的引用計數(shù)加1,然后將指針變量指向新賦值對象,類似于“淺拷貝”。
首先在實現(xiàn)文件中合成屬性變量:@synthesiszename;,然后兩種情況下自定義setter方法如下,自定義了setter方法后編譯器就不會再在編譯期重復(fù)合成setter方法了。
/*retain*/
-(void)setName:(NSString*)newName{
if(name!=newName){
[newNameretain];
//新對象引用計數(shù)加1
[namerelease];
//將指針變量原來的對象釋放掉
name=newName;
//指針變量指向新對象
}
}
第二種情況,copy指當(dāng)對指針變量name賦值新對象時,是將新對象完全copy一份,將copy好的對象復(fù)制給指針變量,即指針指向的是臨時copy出來的對象,而不是新賦值的那個對象,因此新賦值對象不需要引用計數(shù)加1,因為指針變量并沒有指向持有它,類似于“深拷貝”。
/*copy*/
-(void)setName:(NSString*)newName{
if(name!=newName){
idtemp=[newNamecopy];
//將新對象原樣克隆一份
[namerelease];
//將指針變量原來的對象釋放掉
name=temp;
//指針變量指向新對象的克隆體
}
}
6.
如何使用NSURLSession進行網(wǎng)絡(luò)請求?正確答案:在2013年的WWDC上,蘋果公司推出了NSURLConnection的替代方案:NSURLSession。和NSURLConnection一樣,NSURLSession指的也不僅是同名類NSURLSession,它還包括一系列相關(guān)聯(lián)的類。NSURLSession包括了與之前相同的組件:NSURLRequest與NSURLCache,但是將NSURLConnection替換成了NSURLSession、NSURLSessionConfiguration及NSURLSessionTask的3個子類:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。
與NSURLConnection相比,NSURLSession最直接的改進就是可以配置每個session的緩存、協(xié)議、cookie,以及證書策略(CredentialPolicy),甚至跨進程共享這些信息。這將允許程序和網(wǎng)絡(luò)基礎(chǔ)框架之間相互獨立,不會發(fā)生干擾。每個NSURLSession對象都由一個NSURLSessionConfiguration對象進行初始化,后者指定了剛才提到的那些策略以及一些用來增強移動設(shè)備上性能的新選項。
NSURLSessionTask負責(zé)處理數(shù)據(jù)的加載以及文件的數(shù)據(jù)在客戶端與服務(wù)器之間的上傳和下載。它是一個抽象類,一般使用其子類:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。這3個子類封裝了現(xiàn)代程序3個最基本的網(wǎng)絡(luò)任務(wù):獲取數(shù)據(jù)(如JSON或者XML),上傳文件和下載文件。
NSURLSession相關(guān)類的關(guān)系如圖所示。
NSURLSession相關(guān)類的關(guān)系
如何使用NSURLSession像NSURLConnection那樣發(fā)送一個請求呢?基本步驟如下:
1)創(chuàng)建NSURLSessionConfiguration對象對NSURLSession進行配置。
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)建請求對象,默認為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];
/*顯示圖片,注意!此時是異步線程需要在主線程中顯示圖片*/
[selfchangeBg];
}];
[taskresume];
}
7.
Objective-C對象可以被copy的條件是什么?正確答案:Objective-C對象可以被復(fù)制的條件是要遵守NSCopying和NSMutableCoping協(xié)議,默認是不遵守的。可以向遵守NSCopying協(xié)議的類的實例發(fā)送copy消息,也可以向遵守NSMutableCopying協(xié)議的類的實例發(fā)送mutableCopy消息,如果沒有遵守協(xié)議而發(fā)送copy或mutableCopy消息,那么就會出錯。兩個協(xié)議分別對應(yīng)不可變復(fù)制(copy)和可變復(fù)制(mutableCopy),而協(xié)議內(nèi)部的實現(xiàn)方式?jīng)Q定是深拷貝還是淺拷貝。
例如,典型的系統(tǒng)類NSAnay是同時遵守了NSCopying和NSMutableCopying協(xié)議的,因此既可以發(fā)送copy消息,也可以發(fā)送mutableCopy消息。此外,iOS中同時遵守NSCopying協(xié)議和NSMutableCopying協(xié)議的類還有:NSString、NSValue、NSDictionary和NSSet及其子類。
如果想自定義深拷貝或淺拷貝方法,那么就要先遵守對應(yīng)的協(xié)議,并重新實現(xiàn)對應(yīng)的協(xié)議方法。
NSCopying的協(xié)議方法為copyWithZone:
-(id)copyWithZone:(nullableNSZone*)zone{
//深拷貝或淺拷貝實現(xiàn)
}
NSMutableCopying的協(xié)議方法為mutableCopyWithZone:
-(id)mutableCopyWithZone:(nullableNSZone*)zone{
//深拷貝或淺拷貝實現(xiàn)
}
8.
Cocoa中有虛基類的概念嗎?正確答案:Cocoa中沒有虛基類的概念。虛基類是C++語言中為了解決多重繼承二義性問題的,而Objective-C中只有單繼承。
要實現(xiàn)類似C++語言中的多繼承,可以通過protocal來簡單實現(xiàn),因為一個類可以實現(xiàn)多個協(xié)議,類似于Java中一個類可以實現(xiàn)多個接口。
9.
一般的方法method和Objective-C中的選擇器selector有什么區(qū)別?正確答案:selector是一個方法的名字,基于動態(tài)綁定環(huán)境下;method是一個組合體,包含了名字和實現(xiàn)。
可以理解@selector()就是取類方法的編號,它的行為基本可以等同C語言的中函數(shù)指針,只不過C語言中,可以把函數(shù)名直接賦給一個函數(shù)指針,而Objective-C的類不能直接應(yīng)用函數(shù)指針,只能通過一個@selector語法來取,它的結(jié)果是一個SEL類型。這個類型本質(zhì)是類方法的編號(函數(shù)地址)。
10.
iOS中是如何使用自定義字體的?正確答案:字體是軟件開發(fā)中個性化的一個重要元素,系統(tǒng)自帶了很多豐富的字體,但有時候并不能滿足個性化的需求,這時候可以向工程中添加自定義的系統(tǒng)字體,然后就可以像使用系統(tǒng)字體一樣使用。字體文件最常用的為ttf等格式。
導(dǎo)入自定義字體過程很簡單:添加資源包到工程→在info.plist文件中注冊字體→在工程BundleResource中復(fù)制字體資源包→代碼檢測查詢加入的字體并使用。
1.添加資源包
addFile添加字體資源包或者直接將字體包拖到工程資源文件夾下(見圖1)。
圖1
字體文件拖入工程目錄
2.info.plist文件中注冊字體,添加字體資源包
在工程的info.plist屬性列表中添加Fontsprovidedbyapplication數(shù)組屬性,并在其下添加要加入的自定義字體項(見圖2和圖3)。注意,這里在plist文件中寫的是文件的全稱,包括文件擴展名,文件的名字是可以隨便改的,但建議用本來的字體族名,例如這里是:KristenITC,字體族名是不會變的,之后具體代碼中使用的時候是用的字體族名而不是自定義的文件名。本來的字體族名可以右鍵查看字體文件的詳細信息,里面的全稱是本來的字體族名,而名稱是自定義的。字體注冊后將資源包復(fù)制到BundleResource即可(見圖3)。
圖2
配置info.plist
圖3
添加注冊自定義字體項
圖4
字體包復(fù)制到BundleResource
3.檢測是否成功加入字體
在具體使用之前,可以先通過UIFont類提供的方法打印出系統(tǒng)所有的字體列表,并找到剛添加的字體驗證是否添加成功,還可以具體看到資源包有哪些具體的字體樣式,如該字體族的斜體、粗體、粗斜體等。打印字體族列表的代碼如下:
/*檢查自定義字體族是否成功加入*/
/*取出系統(tǒng)安裝了的所有字體族名*/
NSArray*familyNames=[UIFont=familyNames];
NSLog(@"系統(tǒng)所有字體族名:%@",familyNames);
/*打印字體族的所有子字體名(每種字體族可能對應(yīng)多個子樣式字體,例如每種字體族可能有粗體、斜體、粗斜體等等樣式)*/
for(NSString*familyNameinfamilyNames){
/*字體族的所有子字體名*/
NSArray*detailedNames=[UIFontfontNamesForFamilyName:familyName];
NSLog(@"\n字體族%@的所有了字體名:%@",familyName,detailedNames);
}
這里可以從字體組列表中找到剛添加的字體族KristenlTC,結(jié)果如圖5所示。
圖5
已有字體列表
還可以看到字體族KristenITC下的具體字體樣式,這里只有一種也是默認的一種:KristenlTC-Regular(見圖6)。
圖6
字體名
4.使用字體
確定字體加入系統(tǒng)之后就可以像自帶的系統(tǒng)字體一樣直接使用了(字體效果如圖7所示)。
/*設(shè)置label的字體和大小f這里直接使用字體族名也是可以的,有默認的子字體樣式,也可以根據(jù)需求具體到子字體例如這里的:KristenITC-Regular)*/
[_labelsetFont:[UIFontfontWithName:@"KristenITC"size:35.0]];
圖7
字體效果
11.
block有哪幾種定義的方式?正確答案:在Objective-C中,block定義包含了block的類型聲明和實現(xiàn),基本形式如下:
返回值類型(^block名稱)(參數(shù)類型)=^(參數(shù)類型和參數(shù)名){};
其中,返回值類型和參數(shù)可以是空。如果有參數(shù),那么在定義block的時候,必須要標(biāo)明參數(shù)的類型和參數(shù)名。所以,block大致有3種細分的定義方式。
1)沒有返回值,沒有參數(shù)的定義方式。
void(^myBlock)()=^{
//代碼
};
2)有返回值,有參數(shù)的定義方式。
int(^myBlock)(int)=^(inta){
returna;
};
3)有返回值,沒有參數(shù)的定義方式。
int(^myBlock)()=^{
return100;
};
當(dāng)然,block也有屬于自己的類型,就像在Objective-C中,字符串對象屬于NSString類型一樣。block類型的格式就是:
返回值類型(^)(參數(shù)類型)
也就是說,上面第一種定義方式的block類型就是void(^)(),myBlock不是變量名,而是這種block類型的別名。在Objective-C中,可以使用typedef關(guān)鍵字定義block類型,也可以直接使用inline提示符來自動生成block格式。示例代碼如下:
/*使用typedef關(guān)鍵字定義block類型*/
typedefvoid(^myBloek)();
myBlockblock=^{
};
/*使用inline提示符來自動生成block格式*/
<#retumType#>(^<#blockName#>)(<#parameterTypes#>)=^(<#parameters#>){
<#statements#>
};
12.
什么是內(nèi)存泄漏?什么是安全釋放?正確答案:內(nèi)存泄漏指動態(tài)分配內(nèi)存的對象在使用完后沒有被系統(tǒng)回收內(nèi)存,導(dǎo)致該對象始終占用內(nèi)存,又無法通過代碼訪問,屬于內(nèi)存管理出錯,如果出現(xiàn)大量內(nèi)存泄漏,那么會導(dǎo)致系統(tǒng)內(nèi)存不足的問題。由于內(nèi)存泄漏的檢測是程序開發(fā)中不可避免的問題,所以對于程序員而言,一方面要深入理解內(nèi)存管理原則,養(yǎng)成良好的編程習(xí)慣以減少內(nèi)存泄漏情況的發(fā)生;另一方面可以通過各種方法,例如使用Xcode提供的檢測調(diào)試工具Instruments,檢測可能導(dǎo)致內(nèi)存泄漏的代碼,并及時進行優(yōu)化。
安全釋放指釋放掉不再使用的對象的同時不會造成內(nèi)存泄漏或指針懸掛問題的操作。為了保證安全釋放,在對象dealloc后要將其指針置為nil。另外,要嚴格遵守內(nèi)存管理原則,保證對象的引用計數(shù)正確,同時要注意避免引用循環(huán)的出現(xiàn)。
13.
一個tableView是否可以關(guān)聯(lián)兩個不同的datasource數(shù)據(jù)源?正確答案:多個數(shù)據(jù)源是完全可以的,問題的重點是如何關(guān)聯(lián),因為將數(shù)據(jù)源(Model)和tableView視圖的對接工作是程序員完成的,所以數(shù)據(jù)源的多少沒有根本影響。處理上可以分開依次對接,也可以通過數(shù)據(jù)的集合操作先將數(shù)據(jù)整理合并成一個數(shù)據(jù)源,然后對接。
例如,一個表格中的每個cell顯示的是一個人的基本信息,為了簡單這里假設(shè)只有一個頭像和I一個姓名。假設(shè)有兩個數(shù)據(jù)源,一個數(shù)據(jù)源是頭像的url數(shù)組;另一個是姓名的字符串?dāng)?shù)組,對接時完全可以分開在cell數(shù)據(jù)回調(diào)中對接,也可以將兩個數(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;
}
14.
Objective-C中的NSInteger類型和C語言中的int類型有什么區(qū)別?正確答案:在Objective-C中,數(shù)據(jù)類型可以分為基本數(shù)據(jù)類型、對象類型和id類型?;緮?shù)據(jù)類型有int類型、float類型、double類型、char類型、布爾類型等。事實上,Objective-C中的NSInteger也是基本數(shù)據(jù)類型之一。在蘋果的API實現(xiàn)中,NSInterger是一個對int類型和long類型的封裝,它會識別當(dāng)前操作系統(tǒng)的位數(shù),自動返回最大的類型。定義NSInteger類型的代碼如下:
#if__LP64__||(TARGET_OS_EMBEDDED&&!TARGET_OS_IPHONE)||TARGET_OS_WIN32||NS_BUILD_32_LIKE_64
typedeflongNSInteger;
typedefunsignedlongNSUInteger;
#else
typedefintNSInteger;
typedefunsignedintNSUInteger;
#endif
其中,#if、#else、typedef等都屬于預(yù)處理語言。上面這段代碼的意思是,當(dāng)系統(tǒng)是32位系統(tǒng)時,NSInteger類型等價于int類型,即32位,但當(dāng)系統(tǒng)是64位時,NSInteger類型等價于long類型,即64位。
可以看出,NSInteger是long或者int的別名,對應(yīng)的NSUInteger是unsignedlong或者unsignedint的別名。區(qū)別在于,NSInteger會根據(jù)系統(tǒng)是32位機還是64位機來動態(tài)確定自身是整型還是長整型,從而可以很好地兼容兩種機器。因此,當(dāng)開發(fā)者不知道操作系統(tǒng)是什么類型的時候,通常應(yīng)該使用NSInteger,這也是蘋果公司推薦使用的基本數(shù)據(jù)類型之一。
另外,NSInteger是Objective-C基本數(shù)據(jù)類型,不是NSNumber的子類,也不是NSObject的子類。
15.
如何檢測內(nèi)存泄漏?正確答案:檢測內(nèi)存泄漏主要有以下3種方法:
1.靜態(tài)分析
通過靜態(tài)分析可以初步地了解到代碼的一些不規(guī)范的地方或者是存在內(nèi)存泄漏的地方,這是對內(nèi)存泄漏的第一步檢測。當(dāng)然有一些警告是不需要關(guān)心的,可以略過。
2.通過instruments來檢查內(nèi)存泄漏
這個方法能粗略地定位在哪里發(fā)生了內(nèi)存泄漏。方法是完成一個循環(huán)操作,如果內(nèi)存增長為0,那么就證明程序在該次循環(huán)操作中不存在內(nèi)存泄漏;如果內(nèi)存增長不為0,那么就證明有可能存在內(nèi)存泄漏。當(dāng)然具體問題需要具體分析。
3.代碼測試內(nèi)存泄漏
在做這項工作之前,要注意在dealloc的方法中是否已經(jīng)釋放了該對象所擁有的所有對象。觀察對象的生成和銷毀是否配對。準確地說,就是init(創(chuàng)建對象的方法)和dealloc是否會被成對觸發(fā)(簡單來說就是有一次創(chuàng)建對象就有一次dealloc該對象)。
16.
隱式動畫的實現(xiàn)原理是什么?如何禁用圖層的隱式動畫?正確答案:在iOS程序開發(fā)中,有時僅僅改變了圖層或者視圖的一個動畫屬性(例如backgroundColor),就會發(fā)現(xiàn)屬性是平滑地過渡到目標(biāo)值的,屬性值的改變產(chǎn)生了一個動畫效果,而實際上開發(fā)者并沒有顯式地使用動畫,這就是隱式動畫的作用。
隱式動畫指當(dāng)更改視圖的非根圖層的可動畫屬性時,CoreAnimation自動決定如何并且何時去做動畫。動畫的執(zhí)行時間取決于當(dāng)前事務(wù)(CATransaction),而動畫類型取決于圖層行為。
CATransaction類是用來包含一系列屬性動畫集合的機制,任何用指定事務(wù)去改變可動畫屬性都不會立即發(fā)生變化,而是當(dāng)事務(wù)提交的時候開始用一個動畫過渡到新值。CATransaction類沒有屬性或者實例方法,也不能用+alloc和-init方法創(chuàng)建,但是可以用+begin和+commit方法分別來入棧和出棧,這類似于UIView的+beginAnimations:context:和+commitAnimations方法。其次,還可以用+setAnimationDuration方法設(shè)置當(dāng)前事務(wù)的動畫時間,或者+animationDuration方法來獲取值。
改變屬性是CALayer自動應(yīng)用的動畫被稱為“行為”。當(dāng)CALayer的屬性被修改的時候,它會調(diào)用actionForKey:方法,傳遞屬性的名稱。具體的實現(xiàn)原理分為以下幾步:
1)圖層會檢測其是否有代理,并且代理是否實現(xiàn)了CALayerDelegate協(xié)議指定的-actionForLayer:forKey方法。如果有,那么直接調(diào)用并返回結(jié)果。
2)如果圖層沒有代理,或者代理沒有實現(xiàn)-actionForLayer:forKey:方法,那么圖層會接著檢查包含屬性名稱對應(yīng)行為映射的actions字典。
3)如果actions字典沒有包含對應(yīng)的屬性,那么圖層接著在它的style字典搜索屬性名。
4)最后,如果在style字典中也沒有找到對應(yīng)的行為,那么圖層將會直接調(diào)用定義每個屬性的標(biāo)準行為的-defaultActionForKey:方法。
于是就可以解釋UIKit是如何禁用隱式動畫的:每個UIView都是其根圖層的代理,并且實現(xiàn)了-actionForLayer:forKey:方法,只不過返回nil,也就是不執(zhí)行任何動畫。
除了在-actionForLayer:forKey:方法的實現(xiàn)中返回nil外,還可以通過CATransaction的方法+setDisableActions來打開或者關(guān)閉屬性的隱式動畫。使用+setDisableActions臨時取消隱式動畫的代碼如下:
-(void)viewDidLoad{
[superviewDidLoad];
_colorLayer=[CALayerlayer];
_colorLayer.bounds=CGRectMake(0,0,200,200);
_colorLayer.position=self.view.center;
_colorLayer.baekgroundeolor=[UIColorredColor].CGColor;
_colorLayer.delegate=self;
[self.view.layeraddSublayer:_colorLayer];
}
-(void)touchesBegan:(NSSet<UITouch*>*)toucheswithEvent:(UIEvent*)event{
[CATransactionbegin];
//關(guān)閉隱式動畫
CATransaction.disableActions=YES;
CATransaction.animationDuration=5;
_colorLayer.backgroundColor=randomColor.CGColor;
[CATransactioncommit];
}
17.
GCD多線程編程中什么時候會創(chuàng)建新線程?正確答案:對于是否會開啟新線程的情景主要有如下幾種情況:串行隊列中提交異步任務(wù)、串行隊列中提交同步任務(wù)、并發(fā)隊列中提交異步任務(wù)、并發(fā)隊列中提交同步任務(wù)。
(其中主隊列是典型的串行隊列,全局隊列是典型的并發(fā)隊列)
/*創(chuàng)建一個串行隊列*/
dispatch_queue_tserialQueue=dispatch_queue_create("serial.queue".DISPATCH_QUEUE_SERIAL);
/*創(chuàng)建一個并發(fā)隊列*/
dispatch_queue_tconcurrentQueue=dispatch_queue_create("concurrent.queue",DISPATCH_QUEUE_CONCURRENT);
1)串行隊列中提交同步任務(wù):不會開啟新線程,直接在當(dāng)前線程同步地串行執(zhí)行這些任務(wù)。
/*1串行隊列添加同步任務(wù):沒有開肩新線程,全部在主線程串行執(zhí)行*/
dispatch_sync(serialQueue,^{
NSLog(@"SERIAL_SYN_A%@",[NSThreadcurrentThread]);
});
dispatch_sync(serialQueue,^{
NSLog(@"SERIAL_SYN_B%@",[NSThreadcurrentThread]);
});
dispatch_sync(serialQueue,^{
NSLog(@"SERIAL_SYN_C%@",[NSThreadcurrentThread]);
});
2)串行隊列中提交異步任務(wù):會開啟一個新線程,在新子線程異步地串行執(zhí)行這些任務(wù)。
/*2串行隊列添加異步任務(wù):開啟了一個新子線程并共用,串行執(zhí)行*/
dispatch_async(serialQueue,^{
NSLog(@"SERIAL_ASYN_A%@",[NSThreadcurrentThread]);
});
dispatch_async(serialQueue,^{
NSLog(@"SERfAL_ASYN_B%@",[NSThreadcurrentThread]);
});
dispatch_async(serialQueue,^{
NSLog(@"SERIAL_ASYN_C%@",[NSThreadcurrentThread]);
});
3)并發(fā)隊列中提交同步任務(wù):不會開啟新線程,效果和“串行隊列中提交同步任務(wù)”一樣,直接在當(dāng)前線程同步地串行執(zhí)行這些任務(wù)。
/*3并發(fā)隊列添加同步任務(wù):沒有開啟新線程,全部在主線程串行執(zhí)行*/
dispatch_sync(concurrentQueue,^{
NSLog(@"CONCURRENT_SYN_A%@",[NSThreadcurrentThread]);
});
dispatch_sync(concurrentQueue,^{
NSLog(@"CONCURRENT_SYN_B%@",(NSThreadcurrentThread]);
});
dispatch_sync(concurrentQueue,^{
NSLog(@"CONCURRENT_SYN_C%@",[NSThreadcurrentThread]);
});
4)并發(fā)隊列中提交異步任務(wù):會開啟多個子線程,在子線程異步地并發(fā)執(zhí)行這些任務(wù)。
/*4并發(fā)隊列添加異步任務(wù):開啟多個子線程,并發(fā)執(zhí)行多個任務(wù)*/
dispatch_async(concurrentQueue,^{
NSLog(@"CONCURRENT_ASYN_A%@",[NSThreadcurrentThread]);
});
dispatch_async(concurrentQueue,^{
NSLog(@"CONCURRENT_ASYN_B%@",[NSThreadcurrentThread]);
});
dispatch_async(concurrentQueue,^{
NSLog(@"CONCURRENT_ASYN_C%@",[NSThreadcurrentThread]);
});
下圖展示了上面例子中線程的執(zhí)行順序。
線程執(zhí)行順序
總結(jié):
只有異步提交任務(wù)時才會開啟新線程,異步提交到串行隊列會開啟一個新線程,異步提交到并發(fā)隊列可能會開啟多個線程。
同步提交任務(wù)無論提交到并發(fā)隊列還是串行隊列,都不會開啟新線程,都會直接在當(dāng)前線程依次同步執(zhí)行。
注意,如果當(dāng)前線程是主線程,那么不可在當(dāng)前線程提交同步任務(wù),否則會造成線程死鎖而報錯。
18.
Objective-C有私有方法嗎?有私有變量嗎?正確答案:Objective-C是否有私有方法和私有變量關(guān)鍵要看私有的定義。私有主要指通過類的封裝性,將不希望讓外界看到的方法或?qū)傩噪[藏在類內(nèi)部,只有該類可以在內(nèi)部訪問,外部不可見不可訪問。
表面上看,Objective-C中是可以實現(xiàn)私有的變量和方法的,即將它們隱藏不暴露在頭文件中,不可以顯式地直接訪問,但是Objective-C中這種私有并不是絕對的私有,例如即使將變量和方法隱藏在.m實現(xiàn)文件中,開發(fā)者仍然可以利用KVC或runtime運行時機制強行訪問沒有暴露在頭文件的變量或方法。
Objective-C中實現(xiàn)變量和方法“私有”的方式主要有兩種。
1)在類的頭文件中聲明私有變量。
#import<Foundation/Foundation.h>
@interfaceTest:NSObject{
/*頭文件中定義私有變量,默認為@protected*/
@private
NSString*major;
}
@end
2)在.m實現(xiàn)文件頭部的類擴展區(qū)域定義私有屬性或方法,其中方法可不用聲明,直接在實現(xiàn)文件中實現(xiàn)即可,只要不在頭文件聲明的方法都對外不可見。
#import"Test.h"
@interfaceTest(){
/*類擴展區(qū)域定義私有變量,默認就是@private*/
intage;
}
/*類擴展區(qū)域定義私有屬性*/
@property(nonatomic,copy)NSString*name;
/*類擴展區(qū)域定義私有實例方法(可省略聲明,類方法的作用主要就是提供對外接口的,所以一般不會定義為私有)*/
-(void)test;
@end
@implementationTest
/*私有實例方法*/
-(void)test{
NSLog(@"這是個私有實例方法!");
}
@end
利用KVC和runtime暴力訪問私有屬性和變量
KVC訪問變量不受私有權(quán)限的限制,訪問代碼如下:
#import"Test.h"
#import<objc/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);
程序的運行結(jié)果為:
2017-04-0211:58:56.255723CommandLine[99973:3239125]pname:albertpmajor:mathmetics
運行時可以使用class_copyIvarList函數(shù)獲取類對象的Ivar變量列表,然后可使用object_getIvar和object_setIvar運行時函數(shù)對變量進行暴力訪問。
#import"Test.h"
#import<objc/runtime.h>
...
Test*test=[[Testalloc]init];
/*2.運行時暴力訪問私有屬性和私有變量(ARC)*/
/*獲取實例變量列表*/
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);
}
/*訪問私有屬性和變量*/
Ivarv
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年外研版三年級起點選擇性必修1歷史上冊階段測試試卷
- 2025年牛津上海版七年級生物上冊月考試卷
- 2025年粵教滬科版八年級地理下冊階段測試試卷含答案
- 2025年廣東生態(tài)工程職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性測試近5年??及鎱⒖碱}庫含答案解析
- 2025年山東特殊教育職業(yè)學(xué)院高職單招高職單招英語2016-2024歷年頻考點試題含答案解析
- 2025年山東交通職業(yè)學(xué)院高職單招職業(yè)技能測試近5年??及鎱⒖碱}庫含答案解析
- 2025年安徽城市管理職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性測試近5年??及鎱⒖碱}庫含答案解析
- 2025年機械員(設(shè)備管理與維護)技能資格知識考試題庫與答案
- 2025年四川現(xiàn)代職業(yè)學(xué)院高職單招職業(yè)技能測試近5年??及鎱⒖碱}庫含答案解析
- 中考模擬作文:假如我是一名科學(xué)家
- 《 西門塔爾牛臉數(shù)據(jù)集的研究》范文
- 八年級上冊 第三單元 11《簡愛》公開課一等獎創(chuàng)新教學(xué)設(shè)計
- 中小商業(yè)銀行數(shù)字化轉(zhuǎn)型現(xiàn)狀及對策研究
- 親子非暴力溝通培訓(xùn)講座
- 保險投訴處理流程培訓(xùn)
- JJG 707-2014扭矩扳子行業(yè)標(biāo)準
- 2025財年美國國防預(yù)算概覽-美國國防部(英)
- 2024年江西省南昌市中考一模數(shù)學(xué)試題(含答案)
- 《采暖空調(diào)節(jié)能技術(shù)》課件
- 游戲綜合YY頻道設(shè)計模板
- 中興ZCTP 5GC高級工程師認證考試題庫匯總(含答案)
評論
0/150
提交評論