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

下載本文檔

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

文檔簡介

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

如何查看設(shè)備應(yīng)用的crash日志?正確答案:對于一般可重現(xiàn)的bug,可以通過再次運(yùn)行應(yīng)用找到問題所在。但是對于某些偶爾出現(xiàn)的錯(cuò)誤,尤其是內(nèi)存錯(cuò)誤就很難定位了(江南博哥),因?yàn)樵俅芜\(yùn)行可能錯(cuò)誤不會(huì)再次出現(xiàn),所以需要通過查看crash日志,來定位當(dāng)時(shí)發(fā)生錯(cuò)誤的位置。

crash日志可以分成兩種:一種是應(yīng)用發(fā)布AppStore后,用戶的crash日志會(huì)上傳,開發(fā)者可以在iTunesConnect上查看,但前提是用戶在手機(jī)設(shè)置中開啟了“診斷與用量”選項(xiàng),用戶同意分享應(yīng)用崩潰日志等信息給開發(fā)者(具體位置位于:設(shè)置→隱私→診斷與用量)。

另一種是開發(fā)者在開發(fā)測試時(shí)查看crash日志信息。查看測試過程中的日志也有多種途徑,例如運(yùn)行時(shí)可以連接Mac(模擬器或真機(jī)調(diào)試)在本地目錄中查看:~/Library/Logs/CrashReporter/MobileDevice/設(shè)備名稱/。日志文件擴(kuò)展名為.crash或.ips,如圖所示。

日志文件

還有主要是在Xcode中查看日志,位置位于Xcode中Window導(dǎo)航欄下的Devices選項(xiàng),打開會(huì)有模擬器和真機(jī)的設(shè)備列表。選中設(shè)備,在有日志的情況下會(huì)有ViewDeviceLogs選項(xiàng),如圖所示。

Xcode中查看日志

2.

什么是消息推送?和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ā)送推送消息,期間難免會(huì)有延遲。

遠(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,如果一致,那么將消息推送到客戶端。

3.

如何在Category中增加屬性(關(guān)聯(lián)對象)?正確答案:在實(shí)際開發(fā)中,如果為Category添加一個(gè)屬性,那么系統(tǒng)將不會(huì)為這個(gè)屬性設(shè)置訪問器方法,也就是setter和getter方法。這時(shí)候可以使用runtime提供的關(guān)聯(lián)對象方法,動(dòng)態(tài)地為該屬性實(shí)現(xiàn)訪問器方法。

開發(fā)者可以將關(guān)聯(lián)對象想象成一個(gè)Objective-C對象,這個(gè)對象通過一個(gè)預(yù)先設(shè)置好的key連接到類的一個(gè)實(shí)例上。runtime提供了如下方法讓一個(gè)對象連接到其他對象。

voidobjc_setAssociatedObject(idobject,constvoid*key,

idvalue,objc_AssociationPolicypoliey)

參數(shù)object是將要被關(guān)聯(lián)的對象。參數(shù)key是一個(gè)void指針。參數(shù)value是關(guān)聯(lián)對象,它是id類型。參數(shù)policy是指定一個(gè)內(nèi)存管理策略來處理關(guān)聯(lián)對象。如果指定的策略O(shè)BJC_ASSOCIATION_ASSIGN,那么被關(guān)聯(lián)對象釋放時(shí),關(guān)聯(lián)對象不會(huì)被釋放,而如果指定的OBJC_ASSOCIATION_RETAIN或OBJC_ASSOCIATION_COPY,那么關(guān)聯(lián)對象就會(huì)被釋放。另外,還有OBJC_ASSOCIATION_RETAIN_NONATOMIC和OBJC_ASSOCIATIO_COPY_NONATOMIC兩種策略,當(dāng)需要在多個(gè)線程中處理訪問關(guān)聯(lián)對象的多線程代碼時(shí),就會(huì)變得非常有用。

除此之外,runtime還提供了移除關(guān)聯(lián)對象的方法:

voidobjc_removeAssociatedObjects(idobject)

可以使用這個(gè)方法移除所有和參數(shù)object關(guān)聯(lián)的對象,或者使用objc_setAssociatedObject函數(shù)將key指定的關(guān)聯(lián)對象設(shè)置為nil。

下面的示例代碼演示了如何為Person的Category添加一個(gè)屬性。

/*為Person類的Category添加address屬性*/

#import"Person.h"

@interfacePerson(Cate)

@property(nonatomic,strong)NSString*address;

@end

/*在.m文件中為address屬性實(shí)現(xiàn)訪問器方法*/

#import"Person+Cate.h"

#import<o(jì)bje/objc-runtime.h>

@implementationPerson(Cate)

-(id)address{

idvalue=objc_getAssociatedObject(se!f,"address");

returnvalue;

}

-(void)setAddress:(NSString*)address{

objc_setAssociatedObject(self,"address",address,OBJC_ASSOCIATION_RETAIN);

}

@end

/*在控制器中打印屬性值*/

Person*aperson=[[Personalloc]init];

aperson.address=@"China";

NSLog(@"address=%@",aperson.address);

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

2016-11-0319:17:40.94901[2756:152639]aaddress=China

結(jié)果說明已經(jīng)成功地在Category中為類添加了一個(gè)新的屬性,并且能夠正常地使用這個(gè)屬性。事實(shí)上,關(guān)聯(lián)對象是使用哈希表實(shí)現(xiàn)的,將一個(gè)類映射到一張哈希表上,然后根據(jù)key找到關(guān)聯(lián)對象,所以嚴(yán)格來說,關(guān)聯(lián)對象和被關(guān)聯(lián)對象沒有任何關(guān)系,它不是存儲在對象的內(nèi)部。

4.

Objective-C中的可變和不可變類型是什么?正確答案:Objective-C中的mutable和immutable類型對應(yīng)于動(dòng)態(tài)空間分配和靜態(tài)空間分配。最常見的例子是數(shù)組和字典。例如NSArray和NSMutableArray,前者為靜態(tài)數(shù)組(不可變數(shù)組),初始化后長度固定,不可以再動(dòng)態(tài)添加新元素改變數(shù)組長度;后者為動(dòng)態(tài)數(shù)組(可變數(shù)組),可以使用addObject方法動(dòng)態(tài)添加或者使用removeObject方法刪除元素,動(dòng)態(tài)申請新的空間或釋放不需要的空間,伸縮數(shù)組長度。

/*不可變數(shù)組,初始化后不可添加或刪除數(shù)組元素*/

NSArray*array=[[NSArrayalloc]initWithObjects:@1,@2,@3,nil];

/*可變數(shù)組,初始化后可以繼續(xù)添加或刪除數(shù)組元素*/

NSMutableArray*mulArray=[[NSMutableArrayalloc]initWithObjects:@4,@5,@6,nil];

[mulArrayaddObject:@7];

[mulArrayremoveObjectAtIndex:0];

[mulArrayremoveObject:@5];

5.

如何使用NSUserDefault偏好設(shè)置保存數(shù)據(jù)?正確答案:NSUserDefault是iOS系統(tǒng)提供的一個(gè)單例類,通過它可以將用戶的偏好設(shè)置保存到應(yīng)用包的plist文件中,同時(shí)也能讀取保存的數(shù)據(jù)。通過類方法+standardUserDefaults可以獲得NSUserDefault單例。

NSUserDefaults*userDefault=[NSUserDefaultsstandardUserDefaults];

NSUserDefault單例以key-value的形式存儲數(shù)據(jù),key是名稱,value是相應(yīng)的數(shù)據(jù)。使用-setObject:forKey:和-objectForKey:來存/取數(shù)據(jù)。下面的示例演示了一般的存取操作。

-(void)userDefaultSave{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

[defaultssetObject:@"jack"forKey:@"name"];

[defaultssetInteger:10forKey:@"age"];

/*下面的代碼可以省略,這里只是作為演示*/

if([defaultssynchronize]){

NSLog(@"保存成功");

}

}

-(void)userDefaultGet{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

NSString*name=[defaultsobjectForKey:@"name"];

NSIntegerage=[defaultsintegerForKey:@"age"];

NSLog(@"name=%@,age=%zd",name,age);

}

需要注意的是,默認(rèn)情況下NSUserDefaults只能存儲基本對象類型(如NSData、NSString等類型)和基本數(shù)據(jù)類型,直接保存自定義對象將會(huì)拋出類似如下的異常。

Terminatingappduetouncaughtexception'NSInvalidArgumentException',reason:'Attempttoinsertnon-propertylistobject<UIImage:0x608000092d40>,{400,250}forkeyimg'

此時(shí)需要自定義類遵守NSCoding協(xié)議并實(shí)現(xiàn)協(xié)議方法進(jìn)行編碼與反編碼,再通過NSKevedUnarchiver類將自定義對象轉(zhuǎn)為NSData對象,之后才能使用NSUserDefaults進(jìn)行存儲。簡單來說,對于自定義類對象,必須要通過一些方式將其轉(zhuǎn)化為基本類型,即遵循NSCoding協(xié)議。下面的示例展示了如何保存UIImage對象。

-(void)userDefaultSaveImage{

UIImage*img=[UIImageimageNamed:@"1"];

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

/*直接保存將產(chǎn)生錯(cuò)誤:[defaultssetObject:imgforKey:@"img"];*/

/*轉(zhuǎn)為NSData對象*/

NSData*data=UIImageJPEGRepresentation(img,1);

[defaultssetObject:dataforKey:@"img"];

}

-(void)userDefaultGetImage{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

/*轉(zhuǎn)為NSData對象*/

NSData*data=[defaultsobjectForKey:@"img"];

/*轉(zhuǎn)為UIImage對象*/

UIImage*img=[UIImageimageWithData:data];

self.view.layer.contents=(id)img.CGImage;

}

6.

iOS中是如何使用自定義字體的?正確答案:字體是軟件開發(fā)中個(gè)性化的一個(gè)重要元素,系統(tǒng)自帶了很多豐富的字體,但有時(shí)候并不能滿足個(gè)性化的需求,這時(shí)候可以向工程中添加自定義的系統(tǒng)字體,然后就可以像使用系統(tǒng)字體一樣使用。字體文件最常用的為ttf等格式。

導(dǎo)入自定義字體過程很簡單:添加資源包到工程→在info.plist文件中注冊字體→在工程BundleResource中復(fù)制字體資源包→代碼檢測查詢加入的字體并使用。

1.添加資源包

addFile添加字體資源包或者直接將字體包拖到工程資源文件夾下(見圖1)。

圖1

字體文件拖入工程目錄

2.info.plist文件中注冊字體,添加字體資源包

在工程的info.plist屬性列表中添加Fontsprovidedbyapplication數(shù)組屬性,并在其下添加要加入的自定義字體項(xiàng)(見圖2和圖3)。注意,這里在plist文件中寫的是文件的全稱,包括文件擴(kuò)展名,文件的名字是可以隨便改的,但建議用本來的字體族名,例如這里是:KristenITC,字體族名是不會(huì)變的,之后具體代碼中使用的時(shí)候是用的字體族名而不是自定義的文件名。本來的字體族名可以右鍵查看字體文件的詳細(xì)信息,里面的全稱是本來的字體族名,而名稱是自定義的。字體注冊后將資源包復(fù)制到BundleResource即可(見圖3)。

圖2

配置info.plist

圖3

添加注冊自定義字體項(xiàng)

圖4

字體包復(fù)制到BundleResource

3.檢測是否成功加入字體

在具體使用之前,可以先通過UIFont類提供的方法打印出系統(tǒng)所有的字體列表,并找到剛添加的字體驗(yàn)證是否添加成功,還可以具體看到資源包有哪些具體的字體樣式,如該字體族的斜體、粗體、粗斜體等。打印字體族列表的代碼如下:

/*檢查自定義字體族是否成功加入*/

/*取出系統(tǒng)安裝了的所有字體族名*/

NSArray*familyNames=[UIFont=familyNames];

NSLog(@"系統(tǒng)所有字體族名:%@",familyNames);

/*打印字體族的所有子字體名(每種字體族可能對應(yīng)多個(gè)子樣式字體,例如每種字體族可能有粗體、斜體、粗斜體等等樣式)*/

for(NSString*familyNameinfamilyNames){

/*字體族的所有子字體名*/

NSArray*detailedNames=[UIFontfontNamesForFamilyName:familyName];

NSLog(@"\n字體族%@的所有了字體名:%@",familyName,detailedNames);

}

這里可以從字體組列表中找到剛添加的字體族KristenlTC,結(jié)果如圖5所示。

圖5

已有字體列表

還可以看到字體族KristenITC下的具體字體樣式,這里只有一種也是默認(rèn)的一種:KristenlTC-Regular(見圖6)。

圖6

字體名

4.使用字體

確定字體加入系統(tǒng)之后就可以像自帶的系統(tǒng)字體一樣直接使用了(字體效果如圖7所示)。

/*設(shè)置label的字體和大小f這里直接使用字體族名也是可以的,有默認(rèn)的子字體樣式,也可以根據(jù)需求具體到子字體例如這里的:KristenITC-Regular)*/

[_labelsetFont:[UIFontfontWithName:@"KristenITC"size:35.0]];

圖7

字體效果

7.

什么是謂詞?正確答案:謂詞(NSPredicate)是Objective-C中針對數(shù)據(jù)集合的一種邏輯篩選條件,它類似于數(shù)據(jù)庫中SQL語句對數(shù)據(jù)篩選的限制約束條件。Objective-C中的謂詞經(jīng)常用來從數(shù)組(Array)、集合(Set)等數(shù)據(jù)集合中篩選數(shù)據(jù)元素,謂詞約束條件封裝在NSPredicate對象中,可通過類函數(shù)predicateWithFormat和邏輯約束語句進(jìn)行初始化。

這里以用謂詞從對象數(shù)組篩選對象為例展示謂詞的基本使用方法,謂詞對象使用基本的邏輯約束格式化字符串來初始化。假設(shè)有一個(gè)簡單的表(見表)結(jié)構(gòu)有name和age兩個(gè)字段:一個(gè)簡單的表nameageAmy9Lily10Sam12Eric18

謂詞篩選用法的示例代碼如下:

/*其中,Person是一個(gè)簡單的數(shù)據(jù)模型,它有name和age兩個(gè)屬性*/

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

NSArray*objectArray=[[NSArrayalloc]initWithObjects:

[PersonpersonWithName:@"Amy"age:9],

[PersonpersonWithName:@"Lily"age:10],

[PersonpersonWithName:@"Sam"age:12],

[PersonpersonWithName:@"Eric"age:18],

nil];

/*謂詞邏輯約束對象*/

NSPredicate*predicate=[NSPredicatepredicateWithFormat:@"age>10"];

/*篩選數(shù)據(jù)(結(jié)果為Sam,Eric)*/

NSArray*newArray=[objectArrayfilteredArrayUsingPredicate:predicate];

上面的邏輯約束格式化字符串@"age>10"指篩選對象中屬性age大于10的所有對象,格式化字符串可以被看作三部分:左手表達(dá)式、邏輯符號和右手表達(dá)式。其中,左手表達(dá)式是一個(gè)對象的屬性鍵值(鍵路徑);邏輯符號是一個(gè)基本的邏輯運(yùn)算符;右手表達(dá)式是約束范圍。

邏輯運(yùn)算符還有很多,它們與SQL語句中的語法基本相對應(yīng),除了最基本的邏輯運(yùn)算符:>、==、<=、&&等之外,還有邏輯詞IN、CONTAINS、like等。它們的使用情況如下:

/*1.IN:名字為Sam或者Eric的對象*/

NSPredicate*predicate=[NSPredicatepredicateWithFormat:@"nameIN{'Sam','Eric'}"];

1*2.&&:年齡大于10,并且年齡小于20的對象(結(jié)果為Sam,Eric)*/

NSPredicate*predicate=[NSPredicatepredicateWithFormat:@"age>10&&age<20"];

/*3.CONTAINS:名字里有小寫字母a的對象(結(jié)果為Sam)*/

NSPredicate*predicate=[NSPredicatepredicateWithFormat:@"nameCONTAINS'a'"];

/*4.like:正則匹配,?表示一個(gè)個(gè)占位符,*表示任意匹配*/

/*名字第三個(gè)字母為m的對象(結(jié)果為Sam)*/

NSPredicate*predicate=[NSPredicatepredicateWithFormat:@"namelike'??m'"];

/*名字里有小寫字母a的對象(結(jié)果為Sam)*/

NSPredicate*predicate=[NSPredicatepredicateWithFormat:@"namelike'*a*'"];

8.

什么是“懶加載”?正確答案:“懶加載”(Lazyloading)也被叫作“延遲加載”,它的核心思想是把對象的實(shí)例化盡量延遲,直到真正用到的時(shí)候才將其實(shí)例化,這樣做的好處是可以減輕大量對象在實(shí)例化時(shí)對資源的消耗,而不是在程序初始化的時(shí)候就預(yù)先將對象實(shí)例化。另外,“懶加載”可以將對象的實(shí)例化代碼從初始化方法中獨(dú)立出來,從而提高代碼的可讀性,以便于代碼能夠更好地被組織。

最典型的一個(gè)應(yīng)用“懶加載”的例子是在對象的getter方法中實(shí)例化對象的時(shí)候。例如getter方法被重寫,使得在第一次調(diào)用getter方法時(shí)才實(shí)例化對象并將實(shí)例化的對象返回。判斷是否是第一次調(diào)用getter方法可以通過判斷對象是否為空來實(shí)現(xiàn)?!皯屑虞d”的getter方法的實(shí)現(xiàn)模板如下:

/*getter*/

-(NSObject*)object{

if(!_bject){

_object=[[NSObjectalloc]init];

}

return_object;

}

這種實(shí)現(xiàn)方法的缺點(diǎn)是使得getter方法產(chǎn)生副作用,也就是破壞了getter方法的純潔性。因?yàn)榘凑占s定和習(xí)慣,getter方法就是作為接口簡單地將需要的實(shí)例對象返回給外部,這里對getter方法的第一次調(diào)用添加了懶加載模式,在使用者不知情的情況下會(huì)有潛在的隱患。

9.

CGAffineTransform和CATransform3D分別有什么作用?正確答案:CGAffineTransform被稱為“仿射變換”,它被定義在CoreGraphics框架中,主要用于在二維平面對視圖進(jìn)行旋轉(zhuǎn)、縮放和平移。事實(shí)上,CGAffineTransform是一個(gè)可以和二維空間向量(如CGPoint)做乘法的3×2的矩陣。CGAffineTransform中“仿射”的意思是無論使用什么值的變換矩陣,圖層中平行的兩條線在變換之后仍然會(huì)保持平行。

CoreGraphics框架提供了一系列函數(shù)來創(chuàng)建CGAffineTransform實(shí)例,主要有以下幾種:

/*平移*/

CGAffineTransformMakeTranslation(CGFloattx,CGFloatty)

/*縮放*/

GAffineTransformMakeScale(CGFloatsx,CGFloatsy)

/*旋轉(zhuǎn)*/

CGAffineTransformMakeRotation(CGFloatangle)

UIView中的transform屬性或者CALayer中的affineTransform屬性都是CGAffineTransform類型,可以使用它們對視圖或者圖層進(jìn)行仿射變換。此外,CoreGraphics框架還提供了一些可以進(jìn)行混合變換的函數(shù),能夠在一個(gè)變化的基礎(chǔ)上做更深層次的變換,甚至可以將兩個(gè)已經(jīng)存在的變換矩陣進(jìn)行合并。如果要做多次變換的操作,那么這些函數(shù)就會(huì)非常有用。下面用例子來演示一個(gè)包含縮放、旋轉(zhuǎn)和移動(dòng)的變換,示例代碼如下:

-(void)viewDidLoad{

[superviewDidLoad];

_searchImageView=[[UIImageViewalloc]initWithFrame:CGRectMake(([UIScreenmainSereen].bounds.size:width-200)*0.5,([UIScreenmainScreen].bounds.size:height-200)*0.5,200,200)];

_searchImageView.image=[UIImageimageNamed:@"馬"];

[self.viewaddSubview:_searchImageView];

}

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

/*創(chuàng)建一個(gè)空的CGAffineTransform*/

CGAffineTransformtransform=CGAffineTransformIdentity;

/*縮放*/

transform=CGAffineTransformScale(transform,0.5,0.5);

/*旋轉(zhuǎn)*/

transform=CGAffineTransformRotate(transform,M_PI_4);

/*平移*/

transform=CGAffineTransformTranslate(transform,100,0);

_searchImageView.transform=transform;

}

CATransform3D是CoreAnimation結(jié)構(gòu)體。和CGAffineTransform一樣,它也是一個(gè)矩陣。CATransform3D主要用來做更復(fù)雜的關(guān)于CALayer的3D操作。CoreAnimation提供了一系列方法來創(chuàng)建和組合CATransform3D類型的矩陣,這些函數(shù)和CGAffineTransform類似,只是多了一個(gè)z參數(shù),并且旋轉(zhuǎn)函數(shù)除了angle之外還多出了x、y、z3個(gè)參數(shù),這些參數(shù)分別決定了每個(gè)坐標(biāo)軸方向上的旋轉(zhuǎn)。主要函數(shù)如下:

/*3D平移*/

CATransform3DMakeTranslation(CGFloattx,CGFloatty,CGFloattz)

/*3D旋轉(zhuǎn)*/

CATransform3DMakeRotation(CGFloatangle,CGFloatx,CGFloaty,CGFloatz)

/*3D縮放*/

CATransform3DMakeScale(CGFloatsx,CGFloatsy,CGFloatsz)

此外可以通過CATransform3D中的m34元素來控制3D變換的透視效果。m34元素主要用于按比例縮放X和Y的值來計(jì)算遠(yuǎn)離視角的距離。m34的默認(rèn)值是0,可以通過設(shè)置其為-1/d來應(yīng)用透視效果,d代表了視角和屏幕之間的距離,d的值越小,透視效果越強(qiáng),一般設(shè)置為500~1000。示例代碼如下:

-(void)viewDidLoad{

[superviewDidLoad];

_searchImageView=[UIImageViewalloc]initWithFrame:CGRectMake(([UIScreenmainScreen].bounds.size.width-200)*0.5,([UIScreenmainScreen].bounds.size.height-200)*0.5,200,200)];

_searchImageView.image=[UIImageimageNamed:@"馬"];

[self.viewaddSubview:_searchImageView];

/*創(chuàng)建一個(gè)空的CATransform3D*/

CATransform3Dtransform=CATransform3DIdentity;

/*設(shè)置m34元素,增強(qiáng)透視效果*/

transform.m34=-1.0/500.0;

/*3D旋轉(zhuǎn)變換*/

transform=CATransform3DRotate(transform,M_PI_4,0,1,0):

_searchImageView.layer:transform=transform;

}

10.

如何實(shí)現(xiàn)autorealeasepool?正確答案:autorealeasepool(自動(dòng)釋放池)其實(shí)并沒有其自身的結(jié)構(gòu),它是基于多個(gè)AutoreleasePoolPage(一個(gè)C++類)以雙向鏈表組合起來的結(jié)構(gòu),其基本操作都是簡單封裝了AutoreleasePoolPage的操作方法。例如,可以通過push操作添加對象,或者通過pop操作彈出對象,以及通過release操作釋放銷毀對象,對應(yīng)的3個(gè)封裝后的操作函數(shù)為:objc_autoreleasepoolPush、objc_autoreleasepoolPop和objc_autorelease。自動(dòng)釋放池將用完的對象集中起來,統(tǒng)一釋放,起到延遲釋放對象的作用。

自動(dòng)釋放池存儲于內(nèi)存中的棧上,釋放池之間遵循“先進(jìn)后出”原則。例如下面代碼所示的釋放池嵌套。

/*釋放池1*/

@autoreleasepool{

People*person1=[[[Personalloc]init]autoretease];

/*釋放池2*/

@autoreleasepool{

People*person2=[[[Personalloc]init]autorelease];

}

People*person3=[[[Personalloc]init]autorelease];

}

代碼中釋放池1和釋放池2在內(nèi)存中的結(jié)構(gòu)如圖所示,釋放池1先入棧,后出棧;釋放池2后入棧,先出棧。person2對象在釋放池2中,會(huì)被先釋放;person1和person3在釋放池1中,會(huì)后被釋放。

釋放池內(nèi)存結(jié)構(gòu)

自動(dòng)釋放池背后具體的實(shí)現(xiàn)機(jī)制比較復(fù)雜和巧妙,具體細(xì)節(jié)感興趣的讀者可以閱讀下面這篇博文中的討論:/2014/10/15/behind-autorelease/

11.

Git和SVN有什么異同?正確答案:Git和SVN都是用來對工程進(jìn)行版本控制的,它們可以監(jiān)控工程代碼或資源等文件的更改變化,保證正確的內(nèi)容提交或者撤銷恢復(fù)到之前的工程版本,有利于實(shí)現(xiàn)高效的團(tuán)隊(duì)合作。

Git和SVN的主要不同之處在于它們的架構(gòu)原理。簡單地說,Git是分布式的,而SVN是集中式的。當(dāng)使用Git時(shí),每個(gè)開發(fā)者要清楚本地倉庫和遠(yuǎn)程倉庫的概念,由于Git是分布式的,所以每個(gè)開發(fā)者建的本地倉庫都保存了整個(gè)工程的完整備份,而且與SVN不同的是,使用Git可以先在本地提交,在需要的時(shí)候再提交到遠(yuǎn)程倉庫從而推送給其他開發(fā)者看到,提交的過程即是同步的過程。也就是說,Git允許本地倉庫脫離遠(yuǎn)程服務(wù)器倉庫進(jìn)行本地工程的版本控制,而使用SVN每次提交時(shí),都要和中心服務(wù)器倉庫進(jìn)行同步。

由于兩者架構(gòu)的不同,所以Git和SVN中的分支(Branch)概念也是不同的。分支在SVN中是一個(gè)完整的目錄,包含所有的實(shí)際文件,和中心倉庫是保持同步的,如果某個(gè)團(tuán)隊(duì)成員創(chuàng)建新的分支,那么會(huì)同步到所有的成員版本中,所有人都會(huì)受影響,即牽一發(fā)而動(dòng)全身。而在Git下成員創(chuàng)建分支在合并前是不會(huì)影響任何人的,創(chuàng)建分支后可以在本地脫機(jī)進(jìn)行任何操作,測試無誤之后再提交合并到主分支,然后其他成員才能拉取看到。由此可見Git的優(yōu)勢是很明顯的。

另外,Git是把工程的內(nèi)容按照元數(shù)據(jù)的方式存儲,而SVN是把工程內(nèi)容按照文件的方式存儲。Git工程目錄往往比SVN目錄要大,因?yàn)镚it目錄中包含遠(yuǎn)程倉庫所有的數(shù)據(jù),如版本記錄、標(biāo)簽和分支等。

Git的整體結(jié)構(gòu)示意圖如圖所示。

Git的整體結(jié)構(gòu)示意圖

12.

如何理解MVVM設(shè)計(jì)模式?正確答案:隨著業(yè)務(wù)規(guī)模的不斷擴(kuò)大,業(yè)務(wù)邏輯也越來越復(fù)雜,這使得Controller中的任務(wù)越來越繁重,傳統(tǒng)的MVC架構(gòu)已經(jīng)很難滿足低耦合、高內(nèi)聚的設(shè)計(jì)要求。在這樣的背景下,MVVM(Model-View-ViewModel)誕生了。MVVM是由微軟公司提出的一種新的設(shè)計(jì)架構(gòu),它基于MVC架構(gòu),其特點(diǎn)是在View和Model之間多加了一層ViewModel來實(shí)現(xiàn)數(shù)據(jù)的綁定(data-binding),從而很好地解決了MVC中Controller過于臃腫的問題。下圖展示了MVVM設(shè)計(jì)模式的結(jié)構(gòu)。

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

MVVM中的ViewModel有以下幾個(gè)特點(diǎn):

1)ViewModel是有狀態(tài)的。ViewModel有自己的屬性,還會(huì)持有Model對象。

2)ViewModel與UI控件的無關(guān)性。ViewModel并不關(guān)心UI控件的相關(guān)邏輯,只關(guān)心自己的數(shù)據(jù)處理邏輯。

3)易于單元測試。以往的Controller過于復(fù)雜,無法進(jìn)行單元測試,而ViewModel測試起來簡單很多。

4)ViewModel可以抽離出來做轉(zhuǎn)換器給其他項(xiàng)目使用,從而最大程度上實(shí)現(xiàn)了代碼的復(fù)用。

MVVM設(shè)計(jì)模式的目的是幫助MVC設(shè)計(jì)模式中的(Sontroiler瘦身,將數(shù)據(jù)加工的任務(wù)從Controller中解放了出來,使得Controller只需要專注于業(yè)務(wù)分配的工作,讓MVVM中的ViewModel負(fù)責(zé)Model與View之間的通信,并完成通信間的額外操作,如數(shù)據(jù)轉(zhuǎn)換、字符拼接等操作。因此,ViewModel經(jīng)常作為轉(zhuǎn)換器使用,從而提高了代碼的復(fù)用性。ViewModel還能幫助Controller完成復(fù)雜的網(wǎng)絡(luò)請求邏輯,從而大大降低了Controller的復(fù)雜度。這里需要強(qiáng)調(diào)的是,ViewModel具有獨(dú)立性,它并不關(guān)心UI的業(yè)務(wù)邏輯,也不持有任何UI對象,只關(guān)心自己的數(shù)據(jù)處理邏輯是否正確。很多初學(xué)者不清楚ViewModel的用法,往往會(huì)錯(cuò)誤地將UI對象當(dāng)作ViewModel的屬性或者將UI對象的操作放入ViewModel的方法中,這些做法都是不正確的,沒有正真理解MVVM的含義。盡管MVVM帶來了很多好處,降低了代碼的耦合度和復(fù)雜度,但它往往要寫更多的代碼來實(shí)現(xiàn)一個(gè)功能,同時(shí)還增加了工程的規(guī)模,使得工程中的目錄比以前要稍多一些,不易查找文件。MVVM并不是iOS開發(fā)中的“銀彈”,沒有那種方法能完全解決軟件開發(fā)中的問題,但相對于MVC來說,MVVM無疑是一個(gè)更好的選擇。

13.

Objective-C中的NSInteger類型和C語言中的int類型有什么區(qū)別?正確答案:在Objective-C中,數(shù)據(jù)類型可以分為基本數(shù)據(jù)類型、對象類型和id類型?;緮?shù)據(jù)類型有int類型、float類型、double類型、char類型、布爾類型等。事實(shí)上,Objective-C中的NSInteger也是基本數(shù)據(jù)類型之一。在蘋果的API實(shí)現(xiàn)中,NSInterger是一個(gè)對int類型和long類型的封裝,它會(huì)識別當(dāng)前操作系統(tǒng)的位數(shù),自動(dòng)返回最大的類型。定義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)時(shí),NSInteger類型等價(jià)于int類型,即32位,但當(dāng)系統(tǒng)是64位時(shí),NSInteger類型等價(jià)于long類型,即64位。

可以看出,NSInteger是long或者int的別名,對應(yīng)的NSUInteger是unsignedlong或者unsignedint的別名。區(qū)別在于,NSInteger會(huì)根據(jù)系統(tǒng)是32位機(jī)還是64位機(jī)來動(dòng)態(tài)確定自身是整型還是長整型,從而可以很好地兼容兩種機(jī)器。因此,當(dāng)開發(fā)者不知道操作系統(tǒng)是什么類型的時(shí)候,通常應(yīng)該使用NSInteger,這也是蘋果公司推薦使用的基本數(shù)據(jù)類型之一。

另外,NSInteger是Objective-C基本數(shù)據(jù)類型,不是NSNumber的子類,也不是NSObject的子類。

14.

什么是SEL?正確答案:SEL又稱選擇器,表示的是一個(gè)方法的selector的指針。在很多方法名中都可以看到,例如UIControl.h中事件的監(jiān)聽方法:

-(void)addTarget:(nullableid)targetaction:(SEL)actionforControlEvents:(UIControlEvents)controlEvents;

其中,參數(shù)action就是SEL類型。SEL的定義如下:

typedefstructobjc_selector*SEL;

方法的selector用于表示運(yùn)行時(shí)方法的名字。Objective-C在編譯時(shí),會(huì)根據(jù)每個(gè)方法的名字、參數(shù)列表,生成一個(gè)唯一的整型標(biāo)識,這個(gè)標(biāo)識就是SEL。正因?yàn)槠渚哂形ㄒ恍?,所以在Objective-C的同一個(gè)類中,不能存在兩個(gè)同名的方法,即使參數(shù)類型不同也不行。

開發(fā)者可以在運(yùn)行時(shí)添加新的selector,也可以在運(yùn)行時(shí)獲取已存在的selector。可以通過下面3種方法來獲取SEL。

/*在運(yùn)行時(shí)注冊一個(gè)方法,返回一個(gè)SEL指針*/

SELsel_registerName(constchar*str)

/*編譯器提供的方法*/

@selector(selector)

/*通過字符串獲取SEL*/

NSSelectorFromString(NSString*aSelectorName);

事實(shí)上,工程中所有的SEL會(huì)組成一個(gè)Set集合,Set的特點(diǎn)就是具有唯一性,因此SEL也是唯一的。如果想要查找某個(gè)方法,那么只需要找到這個(gè)方法所對應(yīng)的SEL就可以了,SEL實(shí)際上就是根據(jù)方法名Hash轉(zhuǎn)換的一個(gè)字符串。

15.

相對于objective-C而言,Swift有什么新特性?正確答案:Swift是一門新型語言,它借鑒了Haskell、Ruby、Python、C#等語言特性,看上去偏腳本化。Swift仍然支持已有的Cocoa和CocoaTouch框架。

Swift的主要新特性如下:

1)安全:有嚴(yán)格的類型檢查。

2)強(qiáng)大:有高度優(yōu)化的LLVM編譯器。

3)新型:Swift借鑒多種語言特性,表達(dá)更簡單精確。

Swift與Objective-C和C/C++的基本對比見表。C/C++、objective-C和Swift三者基本對比

C/C++Objective-CSwift庫引入#include<stdio.h>#import<Foundation/Foundation.h>importFoundation頭文件#include“Person.h”#import“Person.h”無常量定義#defineSPEED1.0#defineSPEED1.0letSPEED=1.0成員變量聲明intage;intage;varage:Int類方法聲明staticvoidspeak();+(void)speak();classfuncspeak(){...}實(shí)例方法聲明intspeak();-(int)speak();funcspeak(){...}動(dòng)態(tài)內(nèi)存申請Person*person=malloc(sizeof(Person));Person*person=newPerson;Person*person=[Personalloc];Varperson=Person()類方法調(diào)用Person::speak();[Personspeak];Person.speak()實(shí)例方法調(diào)用Person->speak();[personspeak]Person.speak()字符串“String”@“String”“String”

1.從基本的ViewController代碼窺探Objective-C和Swift的區(qū)別

(1)Swift

/*ViewController.swift*|

importUIKit

classViewController:UIViewController{

@IBOutletweakvarlabel1:UILabel!

@IBActionfuncbutton1(sender:AnyObject){

label1.text="HelloiOS!!!"

}

overridefuncviewDidLoad(){

super.viewDidLoad()

//Doanyadditionalsetupafterloadingtheview,typicallyfromanib.

}

overridefuncdidReceiveMemoryWaming(){

super.didReceiveMemoryWarning()

//Disposeofanyresourcesthatcanberecreated.

}

(2)Objective-C

/*ViewController.h*/

#import<UIKit/UIKit.h>

@interfaceViewController:UIViewController

@property(weak,nonatomic)IBOutletUILabel*labell;

-(IBAction)buttonl:(id)sender;

@end

/*ViewController.m*/

#import"ViewController.h"

@interfaceViewController()

@end

@implementationViewController

@synthesizelabel1;

-(void)viewDidLoad{

[superviewDidLoad];

//Doanyadditionalsetupafterloadingtheview,typicallyfromanib.

}

-(void)didReceiveMemoryWaming{

[superdidReceiveMemoryWarning];

//Disposeofanyresourcesthatcanberecreated.

}

-(IBAction)button1:(id)sender{

label1.text=@"HelloiOS!!!";

}

@end

2.SwiR類的定義

整個(gè)類文件都定義在一個(gè)Swift文件內(nèi):

importFoundation

classBall{

/*變量*/

varcenterX:Float

varcenterY:Float

varradius:Float

/*初始化方法*/

init(centerX:Float,centerY:Float,radius:Float){

selfcenterX=centerX

self.centerY=centerY

self.radius=radius

}

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

funcmove(moveX:Float,_moveY:Float){

self.centerX+=moveX

self.centerY+=moveY

}

/*類方法*/

classfuncaClassMethod(){

print("Iamaclassmethod")

}

}

...

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

varball1=Ball(centerX:7.0,centerY:5.0,radius:6.0)

/*方法調(diào)用*/

ball1.move(moveX:1.0,1.0)

Ball.aClassMethod0

3.Objective-C和Swift語言中流程控制語句的比較

(1)Objective-C

/*條件判斷*/

if(a<b){

//Dosomethinghere

}else{

//Doanotherthinghere

}

/*for循環(huán)*/

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

//Dosomethinghere

}

/*while循環(huán)*/

while(count<10){

//Dosomethinghere

}

/*do-while循環(huán)*/

do{

//Dosomcthinghere

}while(count<10);

(2)Swift

/*條件判斷*/

ifa<b{

//Dosomethinghere

}else{

//Doanotherthinghere

}

/*for循環(huán)*/

forinti=0;i<10;i++{

//Dosomethinghere

}

/*while循環(huán)*/

whilecount<10{

//Dosomethinghere

}

/*repeat-while循環(huán)*/

repeat{

//Dosomethinghere

}whilecount<10

4.Objective-C和Swift語言中String字符串的對比

(1)Objective-C

NSString*Str=@"string";

NSString*formatStr=[NSStringstringWithFormat:@"%@andfloat%f",Str,3.1415"];

(2)Swift

/*可變字符串*/

varStr="string"

varStr:String="string"

varStr=String("string")

/*不可變字符串*/

letStr="string"

letStr:String="string"

letStr=String("string")

5.Objective-C和Swift語言中Array和MultableArray的對比

(1)Objective-C

/*靜態(tài)數(shù)組*/

NSArray*array=[[NSArrayalloc]initWithObjects:ball1,ball2,nil];

array[0].radius=10;

/*可變數(shù)組*/

NSMutableArray*mArray=[[NSMutableArrayalloc]initWithCapacity:2];

[mArrayaddObject:ball1];

[mArrayaddObject:ball2];

Ball*newball=[mArrayobjectAtIndex:1];

[mArrayremoveObjectAtIndex:1];

(2)Swift

/*靜態(tài)數(shù)組*/

letmyArray:Array<Ball>=[ball1,ball2]

letmyArray:[Ball]=[ball1,ball2]

letmyArray=[ball1,ball2]

myArray[0].radius=10

/*可變數(shù)組*/

vatmyArray:[Ball]=[]

myArray.append(ball1)

myArray.append(ball2)

varnewBall=myArray[1]

myArray.remove(at:0)

6.Objective-C和Swift語言中UIImageView的使用對比

(1)Objective-C

UIImageView*myImage=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"tiger.png"]];

[self.viewaddSubview:myImage];

myImage.center=CGPointM

溫馨提示

  • 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)僅提供信息存儲空間,僅對用戶上傳內(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

提交評論