版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
iOS程序員面試分類模擬18簡答題1.
Objective-C中的id類型指的是什么?id、nil代表什么?正確答案:id表示Objective-C對象的類型在編寫代碼時(shí)(編譯期)不確定,視為任意(江南博哥)Object類型(即指向任意繼承了NSObject的類的對象或者NSObject對象的指針),直到程序運(yùn)行起來時(shí)才最終確定其類型。
id類似于C/C++中的void*,但id和void*并非完全一樣。id是一個指向繼承了NSObject的Objective-C對象的指針,注意id是一個指針,雖然省略了*號。id和C語言的void*之間需要通過bridge關(guān)鍵字來顯式的橋接轉(zhuǎn)換。具體轉(zhuǎn)換方式示例代碼如下:
idnsobj=[[NSObjectalloc]init];
void*p=(__bridgevoid*)nsobj;
idnsobj=(__bridgeid)p;
Objective-C中的nil定義在objc/objc.h中,表示一個指向空的Objctive-C對象的指針。例如weak修飾的弱引用對象在指向的對象釋放時(shí)會自動將指針置為nil,即空對象指針,來防止指針懸掛。
2.
如何自定義UIViewController之間的轉(zhuǎn)場動畫?正確答案:在實(shí)際開發(fā)中,程序界面常常需要在不同的控制器視圖之間切換,常用的跳轉(zhuǎn)方式有push、pop、present和dismiss等。如果使用這些方式,那么系統(tǒng)會提供默認(rèn)的動畫效果,例如當(dāng)使用-pushViewController:animation:的時(shí)候會產(chǎn)生一個新視圖從右往左推開舊視圖的動畫效果。但是有時(shí)候希望跳轉(zhuǎn)方式能以其他的動畫效果展示,這時(shí)就需要自定義轉(zhuǎn)場動畫。
在開始自定義轉(zhuǎn)場動畫之前,有必要先了解幾個簡單的概念。
1)fromView和toView,在很多API中常常會有fromView和toView,ffomView表示當(dāng)前視圖,即跳轉(zhuǎn)前的視圖,而toView代表跳轉(zhuǎn)后的視圖(或稱為跳轉(zhuǎn)的目標(biāo)視圖)。
2)presentedViewController和presentingViewController,這也是一組相對的概念,presentedViewController表示被modal出的視圖控制器(或稱為跳轉(zhuǎn)的目標(biāo)視圖控制器),而presentingViewController代表源視圖控制器。
3)UIViewControllerTransitioningDelegate協(xié)議用于為跳轉(zhuǎn)動畫提供實(shí)現(xiàn)了UIViewControllerAnimatedTransitioning協(xié)議的對象。
4)UIViewControllerAnimatedTransitioning協(xié)議主要用于控制動畫的展示時(shí)間和動畫展示邏輯。
5)UIViewControllerInteractiveTransitioning協(xié)議即交互式轉(zhuǎn)場動畫代理,這個協(xié)議主要用于交互式動畫。
6)UIViewControllerContextTransitioning協(xié)議即轉(zhuǎn)場動畫上下文協(xié)議,它的作用在于為動畫提供必備的信息。開發(fā)者不應(yīng)該緩存任何關(guān)于動畫的信息,而是應(yīng)該從轉(zhuǎn)場動畫上下文中獲取,這樣可以保證總是獲取到最新的、正確的信息。
要實(shí)現(xiàn)整個轉(zhuǎn)場動畫邏輯需要兩組必需的元素,其一是代表頁面跳轉(zhuǎn)關(guān)系的兩個控制器對象,其二是動畫執(zhí)行邏輯。以下是實(shí)現(xiàn)動畫的步驟:
1)為源控制器和目標(biāo)控制器分別設(shè)置一個遵守UIViewControllerAnimatedTransitioning協(xié)議的代理對象。當(dāng)然也可以設(shè)置為同一個對象。
2)調(diào)用對應(yīng)的跳轉(zhuǎn)方法。此時(shí)系統(tǒng)會自動請求動畫代理提供動畫邏輯對象。
下面的例子展示了一個自定義的跳轉(zhuǎn)動畫效果。
/*設(shè)置transitioningDelegate為當(dāng)前控制器*/
-(void)startCustomControllerTransitionAniamtion1:(UITouch*)touch{
_touchPoint=[touchlocationInView:self.view];
TouchExampleController*VC=[TouchExampleControllernew];
vc.type=3;
vc.transitioningDelegate=self;
[selfpresentViewController:vcanimated:YEScompletion:nil];
}
/*當(dāng)modal時(shí),系統(tǒng)會自動調(diào)用此方法返回一個遵守UIViewControllerAnimatedTransitioning協(xié)議的對象*/
-(nullableid<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController*)presentedpresentingController:(UIViewController*)presentingsourceController:(UIViewController*)source{
TransitionAnimator*animator=[TransitionAnimatornew];
/*將單擊坐標(biāo)傳過去,以確定動畫開始的點(diǎn)*/
animator.touchPoint=_touchPoint;
returnanimator:
}
/*在TransitionAnimator類實(shí)現(xiàn)中,實(shí)現(xiàn)UIViewControllerAnimatedTransitioning協(xié)議*/
@implementationTransitionAnimator
/*設(shè)置動畫時(shí)長*/
-(NSTimeInterval)transitionDuration:(nullableid<UIViewControllerContextTransitioning>)transitionContext{
return1;
}
/*設(shè)置動畫*/
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
/*從上下文中獲取必需信息*/
UIView*fromV=[transitionContextViewForKey:
UITransitionContextFromViewKey];
UIView*toV=[transitionContextviewForKey:UITransitionContextToViewKey];
UIView*containerView=[transitionContextcontainerView];
/*將視圖添加到containerView中*/
[containerViewaddSubview:fromV];
[containerViewaddSubview:toV];
CGFloatscreenWidth=[UIScreenmainScreen].bounds.size.width;
CGFloatscreenHeight=[UIScreenmainScreen].bounds.size.height;
CGPointtempPoint=[containerViewconvertPoint:self.touchPointfromView:[transitionContextviewForKey:UITransitionContextFromViewKey]];
CGRectrect=CGRectMake(tempPoint.x-1,tempPoint.y-1,2,2);
/*使用UIBerizerPath繪制動畫的開始路徑和結(jié)束路徑*/
UIBezierPath*startPath=[UIBezierPathbezierPathWithOvalInRect:reet];
UIBezierPath*endPath=[UIBezierPathbezierPathWithArcCenter:containerView.centerradius:sqrt(screenHeight*screenHeight+screenWidth*screenWidth)startAngle:0endAngle:M_PI*2clockwise:YES];
/*設(shè)置maskLayer*/
CAShapeLayer*maskLayer=[CAShapeLayerlayer];
maskLayer.path=endPath.CGPath;
toV.layer.mask=maskLayer;
/*設(shè)置動畫*/
CABasicAnimation*animation=[CABasicAnimationanimationWithKeyPath:@"path"];
animation.delegate=self;
animation.fromValue=(id)startPath.CGPath;
animation.toValue=(id)endPath.CGPath;
animation.duration=[selftransitionDuration:transitionContext];
[maskLayeraddAnimation:animationforKey:@"custom"];
callback=^{
toV.layer.mask=nil;
/*動畫結(jié)束后一定要調(diào)用此方法完成過渡動畫*/
[transitionContextcompleteTransition:![transitionContexttransitionWasCancelled]];
};
}
-(void)animationDidStop:(CAAnimation*)animfinished:(BOOL)flag{
callback();
}
動畫效果是從單擊坐標(biāo)點(diǎn)開始,以圓圈的形式逐漸展開,如圖所示。
轉(zhuǎn)場動畫
3.
什么是目標(biāo)-動作機(jī)制?正確答案:目標(biāo)-動作(target-action)機(jī)制是一種設(shè)計(jì)模式,用于一個對象在某個事件發(fā)生時(shí)向另一個對象發(fā)送消息。消息中要包含一個selector,用于確定要觸發(fā)的方法,該方法即該機(jī)制中的動作。還要包含一個target(目標(biāo)),表示消息的接收者,例如一個控件,或者更為常見的是它的單元,以插座變量的形式保有其動作消息的目標(biāo)。
目標(biāo)-動作機(jī)制符合軟件開發(fā)中“高內(nèi)聚,低耦合”的設(shè)計(jì)目標(biāo),降低模塊間的耦合度,同時(shí)增強(qiáng)了模塊內(nèi)部的聚合度。目標(biāo)一動作機(jī)制主要用于MVC設(shè)計(jì)模式中V到C的通信,通過該機(jī)制,充當(dāng)V的組件只要在UI事件發(fā)生時(shí)通知C即可,之后的邏輯處理全交由C去進(jìn)一步處理。
典型的例子是UIButton的單擊事件和方法的綁定,當(dāng)按鈕事件發(fā)生時(shí),會觸發(fā)接收者對于該事件所綁定的方法。這里的UIButton按鈕即MVC中的V組件,通過目標(biāo)一動作機(jī)制綁定的selector方法即屬于C中的后續(xù)邏輯處理部分。
[buttonaddTarget:selfaction:@selector(click:)forControlEvents:UIControlEventTouchUpInside];
4.
什么是鍵值編碼KVC?鍵路徑是什么?什么是鍵值觀察KVC?正確答案:1.鍵值編碼KVC
鍵值編碼(KVC)是一種在NSKeyValueCoding非正式協(xié)議下使用字符串標(biāo)志間接訪問對象屬性的一種機(jī)制,也就是訪問對象變量的一種特殊的捷徑。如果一個對象符合鍵值編碼的約定,那么它的屬性就可以通過一個準(zhǔn)確的、唯一的字符串(鍵路徑字符串)參數(shù)進(jìn)行訪問,類似于將所有對象看作Dictionary,鍵路徑為key(實(shí)際為keypath),屬性值即value,通過鍵路徑訪問屬性值。鍵值編碼的間接訪問方式其實(shí)是傳統(tǒng)實(shí)例變量的存取方法訪問的一種替代,也就是另外一種可以訪問對象變量的方法。其中,注意鍵值編碼可以暴力訪問對象的任何變量,無論是否是pirvate私有類型的變量。
開發(fā)者通常是通過存取方法來訪問對象的屬性的,getter方法返回屬性的值,setter方法設(shè)置屬性的值。對于實(shí)例對象,可以直接通過存取方法或者變量名來訪問對象的屬性,但是隨著屬性數(shù)量的增加和對象變量的嵌套深度增大,訪問代碼會隨之增多。相比之下,通過鍵值編碼就可以簡潔而穩(wěn)定地對所有屬性進(jìn)行訪問。
鍵值編碼是Cocoa框架中很基礎(chǔ)的一個概念,像KVO、Cocoa綁定、CoreData等都是基于KVC的。
2.鍵路徑
鍵路徑就是鍵值編碼中某個屬性的key,一個由連續(xù)鍵名組成的字符串,鍵名即屬性名,鍵名之間用點(diǎn)隔開,用于指定一個連接在一起的對象性質(zhì)序列。鍵路徑使開發(fā)者可以獨(dú)立于模型實(shí)現(xiàn)的方式指定相關(guān)對象的性質(zhì)。通過鍵路徑,可以指定對象圖中的一個任意深度的路徑,使其指向相關(guān)對象的某個特定的屬性。
3.鍵值觀察KVO
鍵值觀察(KVO),是基于鍵值編碼實(shí)現(xiàn)的一種觀察者機(jī)制,提供了觀察某一屬性變化的監(jiān)聽方法,用來簡化代碼,優(yōu)化邏輯和組織。
這里提供一個最基本的KVO和KVC的使用示例。假設(shè)有一個專業(yè)類Major,Major有一個專業(yè)名(majorName)私有屬性;一個學(xué)生類Student,Student有一個姓名(name)私有屬性,同時(shí)還有一個專業(yè)(Major)對象變量,這樣就出現(xiàn)了簡單的Major和Student的對象嵌套。Major和Student都繼承自NSObject,都符合鍵值編碼約定,可以定義一個Student變量對其進(jìn)行鍵值編碼和鍵值觀察。示例代碼如下:
/*1.專業(yè)類模型:Major.h*/
@interfaceMajor:NSObject{
@private
NSString*majorName;//私有實(shí)例變量專業(yè)名稱
}
@end
/*2.學(xué)生類模型:Student.h*/
@interfaceStudent:NSObject{
@private
NSString*name;//私有實(shí)例變量姓名
}
@property(nonatomic,strong)Major*major;//學(xué)生專業(yè)
/*3.kvc和kvo之間基本使用方法*/
#import"Student.h"
#import"Major.h"
@interfaceViewController()
@property(nonatomic,strong)Student*student;
@end
@implementationViewController
(void)viewDidLoad{
[superviewDidLoad];
/*初始化學(xué)生Student對象*/
_student=[[Studentalloc]init];
/*初始化學(xué)生的專業(yè)Major對象*/
_student.major=[[Majoralloc]init];
/*1.set:通過KVC設(shè)置Student對象的值(可以強(qiáng)行訪問private變量)*/
[_studentsetValue:@"Sam"forKey:@"name"];
[_studentsetValue:@"ComputerScience"forKeyPath:@"major.majorName"];
/*2.get:通過KVC讀取Student對象的值(可以強(qiáng)行訪問private變量)*/
NSLog(@"%@",[_studentvalueForKey:@"name"]);
NSLog(@"%@",[_studentvalueForKeyPath:@"major.majorName"]);
/*
**3.kvo:添加當(dāng)前控制器為鍵路徑major.majorName的一個觀察者,
**如果major.majorNalne的值改變,那么會通知當(dāng)前控制器從而
**自動調(diào)用下面的observeValueForKeyPath方法,這里傳遞舊值和新值
*/
[_studentaddObserver:selfforKeyPath:@"major.majorName"options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNewcontext:nil];
/*3s后改變major.majorName的值*/
dispatch_after(dispatch_time(DISPATCH_TIMENOW,(int64_t)(3*NSEC_PER_SEC)),dispatch_get_main_queue(),^{
[_studentsetValue:@"SoftwareEngineer"forKeyPath:@"major.majorName"];
});
}
/*監(jiān)聽keyPath值的變化*/
-(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary<NSKeyValueChangeKey,id>*)changecontext:(void*)context{
if([keyPathisEqual:@"major.majorName"]){
/*獲取變化前后的值并打印*/
NSString*oldValue=[changeobjectForKey:NSKeyVatueChangeOldKey];
NSString*newValue=[changeobjectForKey:NSKeyValueChangeNewKey];
NSLog(@"major.majorNamevaluechanged:oldValue:%@newValue:%@",oldValue,newValue);
}
else{
[superobserveValueForKeyPath:keyPathofObject:objectchange:changecontext:context];
}
}
/*移除觀察者釋放資源,防止資源泄漏*/
-(void)dealloc{
[_StudentremoveObserver:selfforKeyPath:@"major.majorName"];
}
@end
可以看到major.majorName就是一個由兩個鍵連接起來的基本鍵路徑,相當(dāng)于用它可以直接訪問屬性的屬性;使用addObserver方法將當(dāng)前控制器注冊為Student對象的觀察者,當(dāng)Student中鍵路徑major.majorName下的值發(fā)生改變時(shí)會通知當(dāng)前控制器,觸發(fā)observeValueForKeyPath監(jiān)聽方法。
5.
objective-C是如何實(shí)現(xiàn)內(nèi)存管理的?正確答案:Objective-C的內(nèi)存管理本質(zhì)上是通過引用計(jì)數(shù)實(shí)現(xiàn)的,每次RunLoop都會檢查對象的引用計(jì)數(shù),如果引用計(jì)數(shù)為0,那么說明該對象已經(jīng)沒有再被使用了,此時(shí)可以對其進(jìn)行釋放了。其中,引用計(jì)數(shù)可以大體分為3種:MRC、ARC和內(nèi)存池。
那么引用計(jì)數(shù)是如何操作的呢?其實(shí)不論哪種引用計(jì)數(shù)方式,它們本質(zhì)上都是在合適的時(shí)機(jī)將對象的引用計(jì)數(shù)加1或者減1。
所以對于引用計(jì)數(shù)可以總結(jié)如下:
1)使對象引用計(jì)數(shù)加1的常見操作有alloc、copy、retain。
2)使對象引用計(jì)數(shù)減1的常見操作有release、autorealease。
自動釋放池是一個統(tǒng)一來釋放一組對象的容器,在向?qū)ο蟀l(fā)送autorelease消息時(shí),對象并沒有立即釋放,而是將對象加入到最新的自動釋放池(即將該對象的引用交給自動釋放池,之后統(tǒng)一調(diào)用release),自動釋放池會在程序執(zhí)行到作用域結(jié)束的位置時(shí)進(jìn)行drain釋放操作,這個時(shí)候會對池中的每一個對象都發(fā)送release消息來釋放所有對象。這樣其實(shí)就實(shí)現(xiàn)了這些對象的延遲釋放。
自動釋放池釋放的時(shí)機(jī)指自動釋放池內(nèi)的所有對象是在什么時(shí)候釋放的,這里要提到程序的運(yùn)行周期RunLoop。對于每一個新的RunLoop,系統(tǒng)都會隱式地創(chuàng)建一個autoreleasepool,RunLoop結(jié)束時(shí)自動釋放池便會進(jìn)行對象釋放操作。autorelease和release的區(qū)別主要是引用計(jì)數(shù)減1的時(shí)機(jī)不同,autorelease是在對象的使用真正結(jié)束的時(shí)候才做引用計(jì)數(shù)減1,而不是收到消息立馬釋放。
retain、release和autorelease的內(nèi)部實(shí)現(xiàn)代碼如下:
-(id)retain{
/*對象引用計(jì)數(shù)加1*/
NSIncrementExtraRefCount(self);
returnself;
}
-(void)release{
/*對象引用計(jì)數(shù)減1,之后如果引用計(jì)數(shù)為0,那么釋放*/
if(NSDecrementExtraRefCountWasZero(self)){
NSDeallocateObject(self);
}
}
-(id)autorelease{
/*添加對象到自動釋放池*/
[NSAutoreteasePooladdObject:self];
returnself;
}
6.
執(zhí)行下面的代碼會發(fā)生什么后果?
Ball*ball=[[[[Ballalloc]init]autorelease]autorelease];正確答案:上面的代碼會導(dǎo)致程序崩潰,因?yàn)檫B續(xù)兩次調(diào)用autorelease方法后,對象被加入到自動釋放池兩次。當(dāng)對象被移除時(shí),自動釋放池將其釋放了不止一次,其中第二次釋放必定導(dǎo)致崩潰。
7.
什么是“應(yīng)用瘦身”?正確答案:“應(yīng)用瘦身”(Appthinning)是美國蘋果公司自iOS9發(fā)布的新特性,它能對AppleStore和操作系統(tǒng)進(jìn)行優(yōu)化,它根據(jù)用戶的具體設(shè)備型號,在保證應(yīng)用特性完整的前提下,盡可能地壓縮和減少應(yīng)用程序安裝包的體積,也就是盡可能減少應(yīng)用程序?qū)τ脩粼O(shè)備內(nèi)存的占用,從而減小用戶下載應(yīng)用程序的負(fù)擔(dān)。Appthinning的實(shí)現(xiàn)主要有以下3種方法:Slicing、Bitcode和On-DemandResources。以下將對這3種方法進(jìn)行介紹。
1.Slicing
在開發(fā)者將完整的應(yīng)用安裝包發(fā)布到AppleStore之后,AppleStore會根據(jù)下載用戶的目標(biāo)設(shè)備型號創(chuàng)建相應(yīng)的應(yīng)用變體(variantsoftheappbundle)。這些變體只包含可執(zhí)行的結(jié)構(gòu)和資源等必要部分,而不需要讓用戶下載開發(fā)者提供的完整安裝包。下圖展示了從開發(fā)者使用Xcode開發(fā)完整應(yīng)用并發(fā)布到AppleStore后被用戶下載到不同設(shè)備上的流程。
應(yīng)用發(fā)布下載流程圖
2.Bitcode
Bitcode是iOS中開發(fā)者的一個可選項(xiàng),如果工程中開啟了Bitcode,那么蘋果會對開發(fā)者編譯后的應(yīng)用二進(jìn)制文件進(jìn)行二次優(yōu)化,將其轉(zhuǎn)換成一種中間代碼(Bitcode),在AppleStore上進(jìn)行編譯和鏈接。Bitcode屬于官方的一種新的優(yōu)化技術(shù),由于很多第三方庫不支持Bitcode,所以很多時(shí)候不得不關(guān)閉Bitcode以保證程序的正常運(yùn)行。
3.On-DemandResources
它是一種“按需供給”的資源加載方式,用戶下載應(yīng)用程序時(shí)不需要下載應(yīng)用程序完整的資源,而是在用戶使用過程中到了某個階段需要用到某些資源(圖片資源和聲音資源等)時(shí),才從后臺的服務(wù)器下載同步,這種方式類似于資源的延遲加載,可以減輕本地內(nèi)存的負(fù)擔(dān)。這種方式在游戲等對資源使用量大的應(yīng)用程序中效果最明顯。另外,這些在后臺延遲下載的資源在內(nèi)存緊張時(shí)可以自動刪除,從而極大地提高內(nèi)存的利用率。
8.
什么是Notification?什么時(shí)候用Delegate或Notification?正確答案:Notification(通知)是Cocoa框架中基于觀察者模式實(shí)現(xiàn)的用于一對多傳播消息的一種機(jī)制。項(xiàng)目中的對象將它們自己或者其他對象添加到通知的觀察者列表里(這個過程又叫通知注冊),其中項(xiàng)目中的所有通知都有一個唯一的字符串標(biāo)識作為通知名唯一確定每個通知,通知源也就是被觀察者可以創(chuàng)建通知對象并發(fā)送到通知中心,通知中心找出所有注冊該通知的對象(觀察者),并將從被觀察者那里收到通知以消息的方式發(fā)送給所有的觀察者們。被觀察者發(fā)送通知是一個同步過程,即發(fā)送者在通知中心成功將該發(fā)送者之前的消息發(fā)送給所有觀察者之前不可以再次發(fā)送通知。另外,通知觸發(fā)的代理方法都必須符合某個單一參數(shù)簽名約定,代理方法的參數(shù)是一個通知對象,參數(shù)里包含著通知名、被觀察者和一個包含其他額外信息的字典。
Delegate和Notification的主要區(qū)別在于前者是一對一的消息傳遞,而后者是一對多的,可以根據(jù)這個特點(diǎn)在使用中進(jìn)行選擇。另外在代理模式中,reciever(接收者)可以返回值給sender(發(fā)送者),實(shí)現(xiàn)一種回調(diào),而觀察者模式中觀察者不可以返回值給被觀察者,因此在需要實(shí)現(xiàn)回調(diào)時(shí)只能選擇代理模式。
9.
按照默認(rèn)法則,哪些關(guān)鍵字生成的對象需要手動釋放?正確答案:起初在MRC(手動引用計(jì)數(shù))中開發(fā)者要自己手動管理內(nèi)存,基本原則是:誰創(chuàng)建,誰釋放,誰引用,誰管理。其中,創(chuàng)建主要始于關(guān)鍵詞new、alloc和copy的使用,創(chuàng)建并持有開始引用計(jì)數(shù)為1,如果引用要通過發(fā)送retain消息增加引用計(jì)數(shù),通過發(fā)送release消息減少引用計(jì)數(shù),那么引用計(jì)數(shù)變?yōu)?后對象會被系統(tǒng)清理釋放?,F(xiàn)在有了ARC(自動引用計(jì)數(shù))后編譯器會自動管理引用計(jì)數(shù),開發(fā)者不再需也不可以手動管理引用計(jì)數(shù)。
使用new、alloc、copy關(guān)鍵字生成的對象和retain了的對象需要手動釋放。被設(shè)置為autorelease的對象不需要手動釋放,會直接進(jìn)入自動釋放池。
10.
如何理解HTTP協(xié)議?正確答案:超文本傳輸協(xié)議(HyperTextTransferProtocol,HTTP)是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議。簡單來說,HTTP是客戶端和服務(wù)器端之間請求和應(yīng)答的標(biāo)準(zhǔn),它可以使瀏覽器(或其他客戶端)更加高效,使網(wǎng)絡(luò)傳輸減少。它不僅保證計(jì)算機(jī)正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內(nèi)容優(yōu)先顯示(如文本先于圖形)等。
一次HTTP操作稱為一個事務(wù),其工作過程可分為4步:
1)客戶端與服務(wù)器需要建立連接。例如,單擊某個超鏈接后,瀏覽器和服務(wù)器將建立通信連接。
2)建立連接后,客戶端發(fā)送一個請求給服務(wù)器,請求方式的格式為:統(tǒng)一資源標(biāo)識符(URL)、協(xié)議版本號,后邊是MIME信息包括請求修飾符、客戶端信息和可能的內(nèi)容。
3)服務(wù)器接到請求后,給予相應(yīng)的響應(yīng)信息,其格式為一個狀態(tài)行,包括信息的協(xié)議版本號、一個成功或錯誤的代碼,后邊是MIME信息包括服務(wù)器信息、實(shí)體信息和可能的內(nèi)容。
4)客戶端接收服務(wù)器所返回的信啟、通過瀏覽器顯示在用戶的顯示屏上,然后客戶機(jī)與服務(wù)器斷開連接。
如果在以上過程中的某一步出現(xiàn)錯誤,那么產(chǎn)生錯誤的信息將返回到客戶端,由顯示屏輸出。對于用戶來說,這些過程是由HTTP自己完成的,用戶只要用鼠標(biāo)單擊,等待信息顯示就可以了。
通常HTTP消息包括客戶端向服務(wù)器的請求消息和服務(wù)器向客戶端的響應(yīng)消息。這兩種類型的消息由一個起始行,一個或者多個頭域,一個指示頭域結(jié)束的空行和可選的消息體組成。HTTP的頭域包括通用頭、請求頭、響應(yīng)頭和實(shí)體頭4個部分。每個頭域由一個域名、冒號(:)和域值組成。域名是大小寫無關(guān)的,域值前可以添加任何數(shù)量的空格符,頭域可以被擴(kuò)展為多行,在每行開始處,使用至少一個空格或制表符。
一個完整的由客戶端發(fā)給服務(wù)器的HTTP請求包含以下兩部分內(nèi)容。
1)請求頭:包含了對客戶端的環(huán)境描述、客戶端請求信息等。
GET/minion.pngHTTP/1.1
//包含了請求方法、請求資源路徑、HTTP協(xié)議版本
Host:86:32812
//客戶端想訪問的服務(wù)器主機(jī)地址
User-Agent:Mozilla/5.0
//客戶端的類型,客戶端的軟件環(huán)境
Accept:text/html
//客戶端所能接收的數(shù)據(jù)類型
Accept-Language:zh-cn
//客戶端的語言環(huán)境
Accept-Encoding:gzip
//客戶端支持的數(shù)據(jù)壓縮格式
2)請求體:客戶端發(fā)給服務(wù)器的具體數(shù)據(jù),例如文件數(shù)據(jù)(POST請求才會有)。
同樣,一個完整的HTTP響應(yīng)中應(yīng)該包含以下兩部分內(nèi)容。
1)響應(yīng)頭:包含了對服務(wù)器的描述、對返回?cái)?shù)據(jù)的描述。
HTTP/1.1200OK
//包含了HTTP協(xié)議版本、狀態(tài)碼、狀態(tài)英文名稱
Server:Apache-Coyote/1.1
//服務(wù)器的類型
Content-Type:image/jpeg
//返回?cái)?shù)據(jù)的類型
Content-Length:56811
//返回?cái)?shù)據(jù)的長度
Date:Mon,23Jun201412:54:52GMT
//響應(yīng)的時(shí)間
2)響應(yīng)體:服務(wù)器返回給客戶端的具體數(shù)據(jù),例如文件數(shù)據(jù)。
常見的響應(yīng)狀態(tài)碼如圖所示。
常見的響應(yīng)狀態(tài)碼
此外,在iOS開發(fā)中發(fā)送HTTP請求有以下幾種方案:
1)NSURLConnection。iOS7之前,通常使用NSURLConnection及關(guān)聯(lián)類,這是iOS開發(fā)中最經(jīng)典的網(wǎng)絡(luò)請求方案。
2)NSURLSession。iOS7之后,逐漸取代NSURLConnection,現(xiàn)在已經(jīng)是iOS開發(fā)中最常用的網(wǎng)絡(luò)請求方式。
3)CFNetwork。它是NSURLConnection和NSURLSession的底層C語言實(shí)現(xiàn),很少在開發(fā)中使用。
4)其他第三方網(wǎng)絡(luò)請求框架,如Objective-C中的AFNetworking和Swift中的Alamofire等。這些網(wǎng)絡(luò)框架也基本上都是對其他3種方案的封裝與拓展。
11.
什么是Cocoa和CocoaTouch?正確答案:Cocoa和CocoaTouch分別是OSX平臺和。iOS平臺的應(yīng)用開發(fā)環(huán)境,兩個平臺的環(huán)境都包含Objective-C的運(yùn)行時(shí)環(huán)境和Foundation框架。
Cocoa用來開發(fā)OSX系統(tǒng)上的應(yīng)用,它主要包括Foundation框架和AppKit界面開發(fā)框架,如圖所示。
Cocoa架構(gòu)圖
CocoaTouch用來開發(fā)iOS系統(tǒng)上的應(yīng)用(主要指iPhone和iPad),它主要包括Foundation框架和UIKit界面開發(fā)框架,如圖所示。
12.
觸發(fā)器分為事前觸發(fā)和事后觸發(fā),二者有什么區(qū)別?語句級觸發(fā)和行級觸發(fā)有什么區(qū)別?正確答案:事前觸發(fā)發(fā)生在事件發(fā)生之前驗(yàn)證一些條件或進(jìn)行一些準(zhǔn)備工作;事后觸發(fā)發(fā)生在事件發(fā)生之后,做收尾工作,保證事務(wù)的完整性。事前觸發(fā)可以獲得之前和新的字段值。語句級觸發(fā)器可以在語句執(zhí)行之前或之后執(zhí)行,而行級觸發(fā)在觸發(fā)器所影響的每一行觸發(fā)一次。
13.
一般的方法method和Objective-C中的選擇器selector有什么區(qū)別?正確答案:selector是一個方法的名字,基于動態(tài)綁定環(huán)境下;method是一個組合體,包含了名字和實(shí)現(xiàn)。
可以理解@selector()就是取類方法的編號,它的行為基本可以等同C語言的中函數(shù)指針,只不過C語言中,可以把函數(shù)名直接賦給一個函數(shù)指針,而Objective-C的類不能直接應(yīng)用函數(shù)指針,只能通過一個@selector語法來取,它的結(jié)果是一個SEL類型。這個類型本質(zhì)是類方法的編號(函數(shù)地址)。
14.
Objective-C中@class代表什么?正確答案:@class相當(dāng)于只是在頭文件聲明一下要用到的類的頭文件(前向聲明),告訴編譯器有這樣一個類的定義但暫時(shí)不要將類的實(shí)現(xiàn)引入,讓該類定義的變量能夠編譯通過,直到運(yùn)行起來時(shí)才去查看類的實(shí)現(xiàn)文件。但實(shí)際上這樣也只能起到在頭文件中聲明該類實(shí)例變量的作用,在.m文件中如果用到類的實(shí)現(xiàn)細(xì)節(jié)(屬性和方法),那么還是要通過#import再次引入類的頭文件。
使用@class的好處是將頭文件的引入延遲了,至少延遲到了.m實(shí)現(xiàn)文件中,這也符合“直到真正用到的時(shí)候再確定引入”的動態(tài)思想,盡量往后拖延,更重要的是這樣也可以有效地避免頭文件的重復(fù)引入甚至循環(huán)引用等問題。
15.
什么是Layer層對象?正確答案:Layer層對象是用來展示可見內(nèi)容的一種數(shù)據(jù)對象,常在視圖中用來渲染視圖內(nèi)容。一般的層對象在界面中可以實(shí)現(xiàn)一些復(fù)雜的動畫或者其他類型的一些復(fù)雜特效。
常見的幾個其自身具有繪制功能的專用Layer有:CATextLayer、CAShapeLayer、CAGradientLayer,這里給出使用示例。其他還有用于3D圖形變換的CATransformLayer,實(shí)現(xiàn)滾動視圖的CAScrollLayer,專門播放視頻的AVPlayerLayer和制作粒子特效的CAEmitterLayer等。它們都是繼承自CALayer的,和CALayer一樣都來自QuartzCore.framework框架。
1.CATextLayer
這個類是用來實(shí)現(xiàn)更加靈活的文字布局和渲染的,它幾乎包含了UILabe1的所有特性并在此基礎(chǔ)上增加了很多更強(qiáng)大的功能,包括字體、尺寸、前景色和下畫線等文字效果,同時(shí)CATextLayer的渲染效率明顯高于UILabel。
通過CALayer來實(shí)現(xiàn)一個UILabel的示例代碼如下(效果見圖):
-(void)viewDidLoad{
[superviewDidLoad];
/*創(chuàng)建一個字符承載視圖*/
UIView*textView=[[UIViewalloc]initWithFrame:CGRectMake(50,50,200,50)];
CATextLayer*text=[CATextLayerlayer];
text.frame=textView.frame;
text.string=@"CAText";
/*文字前景色和背景色*/
text.foregroundColor=[UIColorwhiteColor].CGColor;
text.backgroundColor=[UIColorblackColor].CGColor;
/*文字超出視圖邊界裁剪*/
text.wrapped=YES;
/*文字字體*/
text.font=(__bridgeCFTypeRef)[UIFontsystemFontOfSize:30].fontName;
/*文字居中*/
text.alignmentMode=kCAAlignmentCenter;
/*適應(yīng)屏幕Retina分辨率,防止像素化導(dǎo)致模糊*/
text.contentsScale=[[UIScreenmainScreen]scale];
[textView.layeraddSublayer:text];
[self.viewaddSubview:textView];
}
CATextLayer效果
2.CAShapeLayer
這個類是用來專門繪制矢量圖形的圖形子類,例如可以指定線寬和顏色等利用CGPath繪制圖形路徑,可以實(shí)現(xiàn)圖形的3D變換效果,渲染效率比CoreGraphics快很多,而且可以在超出視圖邊界之外繪制,即不會被邊界裁減掉。
這里展示使用CAShapeLayer繪制一個圓形的實(shí)例代碼如下(效果見圖):
-(void)viewDidLoad{
[superviewDidLoad];
/*創(chuàng)建圓形路徑*/
UIBezierPath*path=[[UIBezierPathalloc]init];
/*起點(diǎn)要在圓心水平右側(cè)半徑長度處*/
[pathmoveToPoint:CGPointMake(200,100)];
/*添加圓形弧路徑*/
[pathaddAreWithCenter:CGPointMake(150,100)radius:50startAngle:0endAngle:2*M_PIclockwise:YES];
/*創(chuàng)建圖形層*/
CAShapeLayer*layer=[CAShapeLayerlayer];
/*路徑線的顏色*/
layer.strokeColor=[UIColorredColor].CGColor;
/*閉合圖形填充色,這里設(shè)置透明*/
layer.fillColor=[UIColorclearColor].CGColor;
/*線寬*/
layer.lineWidth=10;
/*線的樣式:端點(diǎn)、交點(diǎn)*/
layer.lineCap=kCALineCapRound;
layer.lineJoin=kCALineJoinRound;
/*設(shè)置圖形路徑*/
layer.path=path.CGPath;
[self.view.layeraddSublayer:layer];
}
@end
CAShapeLayer繪制效果
3.CAGradientLayer
它是一個硬件加速的高性能繪制圖層,主要用來實(shí)現(xiàn)多種顏色的平滑漸變效果。這里給出一個3種顏色從正方形左上角到右下角的漸變效果示例代碼(效果見圖6):
-(void)viewDidLoad{
[superviewDidLoad];
/*創(chuàng)建layer承載視圖*/
UIView*containerView=[[UIViewalloc]initWithFrame:CGRectMake(50,50,150,150)];
CAGradientLayer*layer=[CAGradientLayerlayer];
layer.frame=containerView.bounds;
/*依次設(shè)置漸變顏色數(shù)組*/
layer.colors=@[(__bridgeid)[UIColorgreenColor].CGColor,(__bridgeid)[UIColoryellowColor].CGColor,(__bridgeid)[UIColororangeColor].CGColor];
/*顏色從起點(diǎn)到終點(diǎn)按比例分段位置*/
layer.locations=@[@0,0,@0.3,@0.5];
/*顏色漸變的起點(diǎn)和終點(diǎn):(0,0)~(1,1)表示左上角到右下角*/
layer.startPoint=CGPointMake(0,0);
layer.endPoint=CGPointMake(1,1);
[containerView.layeraddSublayer:layer];
[self.viewaddSubview:containerView];
}
CAGradientLayer繪制效果
16.
在Objective-C中,常量有哪幾種類型?正確答案:在Objective-C中,常量有以下4種類型。
(1)整型常量
整型常量由一個或多個int類型數(shù)字的序列組成。值12、0和-10都是合法的整型常量。數(shù)字之間不允許插入空格,并且不能使用逗號等特殊符號(例如,1,000就是一個非法的整型常量,它必須寫作1000)。
(2)浮點(diǎn)型常量
浮點(diǎn)型常量和整型常量的數(shù)據(jù)正好相反,浮點(diǎn)型常量可以存儲包含小數(shù)位數(shù)字的值。例如0.01、3.1415926、-0.002等都是合法的浮點(diǎn)型常量。
(3)字符常量
字符類型的常量可以存儲單個字符。將字符放入一對單引號中就能得到字符常量。因此,“a”“.”“;”和“100”都是合法的字符常量。需要注意的是,第4個表示字符100,它和數(shù)字100并不相同。
(4)符號常量
前面3種常量可統(tǒng)稱為直接常量,而符號常量是使用標(biāo)識符代表一個常量。符號常量在使用之前必須先定義,其一般形式為:
#define標(biāo)識符常量
示例代碼如下:
#definePRICE10
main(){
intnum,total;
num=10;
total=num*PRICE;
printf("total=%d",total);
}
以上程序的輸出為100。在本例中,#define是一條預(yù)處理命令(在后面的預(yù)處理程序章節(jié)中將進(jìn)一步介紹),其功能是將標(biāo)識符定義為其后的常量值。習(xí)慣上符號常量的標(biāo)識符用大寫字母,變量標(biāo)識符用小寫字母,以示區(qū)別。
17.
NSMutableDictionary中setValue和setObject有什么區(qū)別?正確答案:需要了解蘋果公司API中關(guān)于NSMutableDictionary中setValue:forKey:方法和setObject:forKey:方法的定義。其中,對應(yīng)setValue:forKey:方法的API是:
@interfaceNSMutableDictionary<KeyType,ObjectType>(NSKeyValueCoding)
/*Send
-setObject:forKey:tothereceiver,unlessthevalueisnil,inwhichcasesend-removeObjectForKey:*/
-(void)setValue:(nullableObjectType)valueforKey:(NSString*)key;
@end
官方的注釋說得很清楚,當(dāng)發(fā)送setValue:forKey:消息給一個NSMutableDictionary類型的對象時(shí),一般情況下仍然是調(diào)用了setObject:forKey方法,除非,當(dāng)參數(shù)value的值是nil的時(shí)候,就會轉(zhuǎn)而調(diào)用removeObjectForKey:清除這個鍵值對。
對應(yīng)setobject:forKey:方法的API是:
-(void)setObject:(id)anObjectforKey:(id<NSCopying>)aKey;
這里需要注意的是,這個方法中Key是一個遵循了NSCopying協(xié)議的id類型對象,并不是NSString類型的字符串,只不過在實(shí)踐中通常使用NSString而己。示例代碼如下:
NSMutableDictionary*dic=[NSMutableDictionarydictionary];
[dicsetObject:@"1"forKey:[NSNumbernumberWithInt:1]];
[dicsetValue:@"2"forKey:[NSNumbernumberWithInt:2]];
NSLog(@"value1=%@value2=%@",dic[[NSNumbernumberWithInt:1]],dic[[NSNumbernumberWithInt:2]]);
程序的輸出結(jié)果為:
2016-10-1117:12:40:865test[5827:890647]value1=1value2=2
事實(shí)上,當(dāng)試圖為setValue:forKey:設(shè)置一個非NSString類型的Key時(shí)(此處是NSNumber類型),系統(tǒng)會發(fā)出“uncompatiblepointertypessending'NSNumber*_Nonnull'toparameteroftype'NSString*_Nonnull'”的警告,但是不會拋出異常,仍然會正常打印出結(jié)果。
綜上所述,NSMutableDictionary中setValue:forKey:方法和setObject:forKey:方法的主要區(qū)別有:
1)setObject:forKey:方法是NSMutableDictionary類特有的,只有NSMutableDictionary類及其子類的實(shí)例化對象能夠使用,而setValue:forKey:方法是KVC的主要方法,只要遵循了NSCoding協(xié)議的對象都能夠使用。
2)setObject:forKey:方法中參數(shù)value的值不能為nil,否則會拋出異常。而setValue:forKey:中value能夠?yàn)閚il,只是當(dāng)value為nil的時(shí)候,會自動調(diào)用removeObject:forKey:方法。
3)setValue:forKey:中key的參數(shù)只能夠是NSString類型,而setObject:forKey:的key可以是任何類型的對象類型。
18.
Objective-C的類可以多重繼承嗎?可以實(shí)現(xiàn)多個接口嗎?重寫一個類的方式用繼承好還是類別好?為什么?正確答案:Objective-C的類只支持單繼承,不可以多重繼承。
Objective-C可以利用protocol代理協(xié)議實(shí)現(xiàn)多個接口,通過實(shí)現(xiàn)多個接口完成類似C++的多重繼承。在Objective-C中多態(tài)特性是通過protocol(協(xié)議)或者Category(類別)來實(shí)現(xiàn)的。protocol定義的接口方法可以被多個類實(shí)現(xiàn),Category可以在不變動原類的情況下進(jìn)行方法重寫或者擴(kuò)展。
重寫一個類一般情況下使用類別更好,因?yàn)橛肅ategory去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關(guān)系。
19.
AppID和BundleID有什么不同?正確答案:AppID是一個組合字符串,它包括兩個部分,一個是開發(fā)團(tuán)隊(duì)的ID,另一個是標(biāo)識應(yīng)用的BundleID,它們之間是用點(diǎn)隔開的。開發(fā)團(tuán)隊(duì)的ID是蘋果公司提供給開發(fā)者的,這個ID可以唯一標(biāo)識一個開發(fā)團(tuán)隊(duì);BundleID是開發(fā)者自定義的唯一標(biāo)識一個應(yīng)用的。一個團(tuán)隊(duì)的ID和不同的BundleID組合可以得到不同的AppID,這個AppID就可以標(biāo)識該團(tuán)隊(duì)的不同的應(yīng)用,開發(fā)者需要通過AppID來使自己的應(yīng)用可以獲取豐富的蘋果服務(wù),如iCloud服務(wù)等。
BundleID也就是AppID的后半部分,是一個App應(yīng)用的唯一標(biāo)識符,
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園六一運(yùn)動課程設(shè)計(jì)
- 2024年房產(chǎn)獨(dú)家設(shè)計(jì)委托協(xié)議3篇
- 幼兒昆蟲類語言課程設(shè)計(jì)
- 怎么學(xué)高中課程設(shè)計(jì)
- 小班登山課程設(shè)計(jì)
- 小班戶外課程設(shè)計(jì)案例
- 小黑魚繪本創(chuàng)意課程設(shè)計(jì)
- 材料力學(xué)梁的課程設(shè)計(jì)
- 幼兒園火山游戲課程設(shè)計(jì)
- 2024年科技出版社專業(yè)圖書采購合作協(xié)議書3篇
- 過敏性紫癜-教學(xué)課件
- GB/T 18344-2016汽車維護(hù)、檢測、診斷技術(shù)規(guī)范
- 神態(tài)描寫課件
- 醫(yī)惠內(nèi)鏡消毒質(zhì)量追溯系統(tǒng)
- 如何提高基層干部群眾工作能力課件
- 風(fēng)險(xiǎn)分級管控與隱患排查治理雙重預(yù)防體系建設(shè)資料匯編
- 2022年讀者出版集團(tuán)有限公司招聘筆試試題及答案解析
- NB∕T 33009-2021 電動汽車充換電設(shè)施建設(shè)技術(shù)導(dǎo)則
- 大學(xué)《傳播學(xué)概論》試卷及答案
- 工程設(shè)計(jì)費(fèi)收費(fèi)標(biāo)準(zhǔn)
- -堅(jiān)定目標(biāo)贏在執(zhí)行 主題班會課件
評論
0/150
提交評論