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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

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

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

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

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

日志文件

還有主要是在Xcode中查看日志,位置位于Xcode中Window導航欄下的Devices選項,打開會有模擬器和真機的設備列表。選中設備,在有日志的情況下會有ViewDeviceLogs選項,如圖所示。

Xcode中查看日志

2.

什么是消息推送?和NotificatiOil有什么區(qū)別?正確答案:消息推送指在App關閉時(不在前臺運行時),仍然向用戶發(fā)送App的內(nèi)部消息。消息推送通知和Objective-C中的Notification通知機制不同,推送的消息是給用戶看的,也就是可見的,而通知機制是Objective-C語言中對象間通信的一種機制,基于觀察者模式,目的是觸發(fā)內(nèi)部事件,減小類之間的耦合度,對用戶是不可見的。

推送消息的可見形式主要有以下幾種:

1)鎖屏界面的橫幅推送消息。

2)頂部通知欄的橫幅推送消息。

3)應用圖標上的代表消息數(shù)量的紅色數(shù)字。

4)菜單頁面彈出框提示。

5)播放聲音提示。

下圖所示是iPhone中QQ推送的設置界面。

QQ推送的設置界面

下圖所示為iPhone中消息推送的形式。

iPhone中消息推送的形式

iOS開發(fā)中有兩種類型的消息推送:本地消息推送(LocalNotification)和遠程消息推送(RemoteNotification)。

1)本地消息推送:本地消息推送很簡單,不需要聯(lián)網(wǎng),不需要服務器,由客戶端應用直接發(fā)出推送消息,一般通過定時器在指定的時間進行消息推送。

2)遠程消息推送:遠程消息推送過程略為復雜,需要客戶端從蘋果公司的APNS(ApplePushNotificationSerwices)服務器注冊獲得當前用戶的設備令牌并發(fā)送給應用的服務器,然后應用的服務器才可以通過APNS服務器間接地向客戶端發(fā)送推送消息,期間難免會有延遲。

遠程消息推送的具體流程如圖所示,開發(fā)中要和服務器合作共同完成。

遠程消息推送流程圖

①App客戶端向APNS服務器發(fā)送設備的UDID和BundleIdentifier。

②APNS服務器對傳過來的信息加密生成一個deviceToken,并返回給客戶端。

③客戶端將當前用戶的deviceToken發(fā)送給自己應用的服務器。

④自己應用的服務器將得到的deviceToken保存,需要的時候利用deviceToken向APNS服務器發(fā)送推送消息。

⑤APNS服務器接收到自己應用的服務器的推送消息時,驗證傳過來的deviceToken,如果一致,那么將消息推送到客戶端。

3.

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

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

voidobjc_setAssociatedObject(idobject,constvoid*key,

idvalue,objc_AssociationPolicypoliey)

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

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

voidobjc_removeAssociatedObjects(idobject)

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

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

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

#import"Person.h"

@interfacePerson(Cate)

@property(nonatomic,strong)NSString*address;

@end

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

#import"Person+Cate.h"

#import<obje/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);

程序的打印結果如下:

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

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

4.

Objective-C中的可變和不可變類型是什么?正確答案:Objective-C中的mutable和immutable類型對應于動態(tài)空間分配和靜態(tài)空間分配。最常見的例子是數(shù)組和字典。例如NSArray和NSMutableArray,前者為靜態(tài)數(shù)組(不可變數(shù)組),初始化后長度固定,不可以再動態(tài)添加新元素改變數(shù)組長度;后者為動態(tài)數(shù)組(可變數(shù)組),可以使用addObject方法動態(tài)添加或者使用removeObject方法刪除元素,動態(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ù)據(jù)?正確答案:NSUserDefault是iOS系統(tǒng)提供的一個單例類,通過它可以將用戶的偏好設置保存到應用包的plist文件中,同時也能讀取保存的數(shù)據(jù)。通過類方法+standardUserDefaults可以獲得NSUserDefault單例。

NSUserDefaults*userDefault=[NSUserDefaultsstandardUserDefaults];

NSUserDefault單例以key-value的形式存儲數(shù)據(jù),key是名稱,value是相應的數(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);

}

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

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

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

-(void)userDefaultSaveImage{

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

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

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

/*轉為NSData對象*/

NSData*data=UIImageJPEGRepresentation(img,1);

[defaultssetObject:dataforKey:@"img"];

}

-(void)userDefaultGetImage{

NSUserDefaults*defaults=[NSUserDefaultsstandardUserDefaults];

/*轉為NSData對象*/

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

/*轉為UIImage對象*/

UIImage*img=[UIImageimageWithData:data];

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

}

6.

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

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

1.添加資源包

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

圖1

字體文件拖入工程目錄

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

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

圖2

配置info.plist

圖3

添加注冊自定義字體項

圖4

字體包復制到BundleResource

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

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

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

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

NSArray*familyNames=[UIFont=familyNames];

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

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

for(NSString*familyNameinfamilyNames){

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

NSArray*detailedNames=[UIFontfontNamesForFamilyName:familyName];

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

}

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

圖5

已有字體列表

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

圖6

字體名

4.使用字體

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

/*設置label的字體和大小f這里直接使用字體族名也是可以的,有默認的子字體樣式,也可以根據(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和邏輯約束語句進行初始化。

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

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

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

/*數(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ù)(結果為Sam,Eric)*/

NSArray*newArray=[objectArrayfilteredArrayUsingPredicate:predicate];

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

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

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

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

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

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

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

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

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

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

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

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

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

8.

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

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

/*getter*/

-(NSObject*)object{

if(!_bject){

_object=[[NSObjectalloc]init];

}

return_object;

}

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

9.

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

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

/*平移*/

CGAffineTransformMakeTranslation(CGFloattx,CGFloatty)

/*縮放*/

GAffineTransformMakeScale(CGFloatsx,CGFloatsy)

/*旋轉*/

CGAffineTransformMakeRotation(CGFloatangle)

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

-(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)建一個空的CGAffineTransform*/

CGAffineTransformtransform=CGAffineTransformIdentity;

/*縮放*/

transform=CGAffineTransformScale(transform,0.5,0.5);

/*旋轉*/

transform=CGAffineTransformRotate(transform,M_PI_4);

/*平移*/

transform=CGAffineTransformTranslate(transform,100,0);

_searchImageView.transform=transform;

}

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

/*3D平移*/

CATransform3DMakeTranslation(CGFloattx,CGFloatty,CGFloattz)

/*3D旋轉*/

CATransform3DMakeRotation(CGFloatangle,CGFloatx,CGFloaty,CGFloatz)

/*3D縮放*/

CATransform3DMakeScale(CGFloatsx,CGFloatsy,CGFloatsz)

此外可以通過CATransform3D中的m34元素來控制3D變換的透視效果。m34元素主要用于按比例縮放X和Y的值來計算遠離視角的距離。m34的默認值是0,可以通過設置其為-1/d來應用透視效果,d代表了視角和屏幕之間的距離,d的值越小,透視效果越強,一般設置為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)建一個空的CATransform3D*/

CATransform3Dtransform=CATransform3DIdentity;

/*設置m34元素,增強透視效果*/

transform.m34=-1.0/500.0;

/*3D旋轉變換*/

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

_searchImageView.layer:transform=transform;

}

10.

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

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

/*釋放池1*/

@autoreleasepool{

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

/*釋放池2*/

@autoreleasepool{

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

}

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

}

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

釋放池內(nèi)存結構

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

11.

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

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

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

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

Git的整體結構示意圖如圖所示。

Git的整體結構示意圖

12.

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

MVVM設計模式結構

MVVM中的ViewModel有以下幾個特點:

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

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

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

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

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

13.

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類型的封裝,它會識別當前操作系統(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等都屬于預處理語言。上面這段代碼的意思是,當系統(tǒng)是32位系統(tǒng)時,NSInteger類型等價于int類型,即32位,但當系統(tǒng)是64位時,NSInteger類型等價于long類型,即64位。

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

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

14.

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

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

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

typedefstructobjc_selector*SEL;

方法的selector用于表示運行時方法的名字。Objective-C在編譯時,會根據(jù)每個方法的名字、參數(shù)列表,生成一個唯一的整型標識,這個標識就是SEL。正因為其具有唯一性,所以在Objective-C的同一個類中,不能存在兩個同名的方法,即使參數(shù)類型不同也不行。

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

/*在運行時注冊一個方法,返回一個SEL指針*/

SELsel_registerName(constchar*str)

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

@selector(selector)

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

NSSelectorFromString(NSString*aSelectorName);

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

15.

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

Swift的主要新特性如下:

1)安全:有嚴格的類型檢查。

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

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

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(){...}實例方法聲明intspeak();-(int)speak();funcspeak(){...}動態(tài)內(nèi)存申請Person*person=malloc(sizeof(Person));Person*person=newPerson;Person*person=[Personalloc];Varperson=Person()類方法調(diào)用Person::speak();[Personspeak];Person.speak()實例方法調(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類的定義

整個類文件都定義在一個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

}

/*實例方法*/

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)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論