




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
iOS程序員面試分類模擬9簡答題1.
UIView和CALayer的區(qū)別與聯(lián)系是什么?正確答案:1.UIView和CALayer是什么?
CALayer是動(dòng)畫中經(jīng)常使用的一個(gè)類,它包含在Qu(江南博哥)anzCore框架中。CALayer類在概念上和UIView類似,同樣是一些被層級(jí)關(guān)系樹管理的矩形塊,也可以包含一些內(nèi)容(像圖片、文本或者背景色),管理子圖層的位置。它們有一些方法和屬性用來做動(dòng)畫和變換。使用CoreAnimation開發(fā)動(dòng)畫的本質(zhì)就是將CALayer中的內(nèi)容轉(zhuǎn)化為位圖供硬件操作。
CALayer是一個(gè)比UIView更底層的圖形類,是對(duì)底層圖形API(OpenGLES)一層層封裝后得到的一個(gè)類,用于展示一些可見的圖形元素,保留了一些基本的圖形化操作,但同時(shí)由于相對(duì)高度的封裝,使得操作使用變得很簡單。CALayer用于管理圖形元素,甚至可以制作動(dòng)畫,它保留了一些幾何屬性,如位置、尺寸、圖形變換等。一般的CALaver是作為UIView背后的支持角色,在創(chuàng)建了一個(gè)UIViewr的同時(shí)也存在一個(gè)相應(yīng)的CALayer。UIView作為CALayer的代理角色去實(shí)現(xiàn)一些功能,例如常見的為UIView制作一個(gè)圓角,就會(huì)用到UIView背后的layer操作:
view.layer.cornerRadius=10;
CALayer可以通過UIView很方便地展示操作UI元素,但是CALayer自身單獨(dú)也可以展示和操作可見元素,且靈活度更高,它自身有一些可見可設(shè)置的屬性,如背景色、邊框、陰影等。
另外,UIView簡單來說是一個(gè)可以在里面渲染可見內(nèi)容的矩形框,它里面的內(nèi)容可以和用戶進(jìn)行交互,UIView可以對(duì)交互事件進(jìn)行處理。除了其背后CALayer的圖形操作支持,UIView自身也有像設(shè)置背景色等最基本的屬性設(shè)置。
2.UIView和CALayer的聯(lián)系
UIView和CALayer的主要聯(lián)系上面已經(jīng)提到,CALayer在UIView背后提供更加豐富靈活的圖形操作,UIView作為CALayer的代理更加快速地幫CALayer顯示一些常用的UI元素并提供交互。
另外,UIView類是所有視圖的基類,CALayer是圖層類。事實(shí)上,UIView和CAlayer是平行的層級(jí)關(guān)系。每一個(gè)UIView都有一個(gè)CALayer實(shí)例的圖層屬性,視圖的責(zé)任就是創(chuàng)建并管理圖層,以確保當(dāng)子視圖在層級(jí)關(guān)系中被添加或者被移除的時(shí)候,與它們相關(guān)聯(lián)的圖層也同樣在層級(jí)關(guān)系樹中有相同的操作。
3.UIView和CALayer的區(qū)別
1)CALayer無法響應(yīng)用戶事件。UIView和CALayer的最明顯區(qū)別在于它們的可交互性,即UIViewr可以響應(yīng)用戶事件,而CALayer不可以,原因可以從這兩個(gè)類的繼承關(guān)系上看出(見圖)。UIView是繼承自UIResponder的,決定了UIView類及其子類能夠通過響應(yīng)鏈(iOS通過視圖層級(jí)關(guān)系來傳遞觸摸事件)接收并響應(yīng)用戶事件。而CALayer直接繼承于NSObject類,所以它不清楚具體的響應(yīng)鏈,也就無法響應(yīng)用戶事件。
CALayer和UIView繼承關(guān)系
2)分工不同。UIView類側(cè)重于對(duì)顯示內(nèi)容的管理和整體布局,而CALayer側(cè)重于顯示內(nèi)容的繪制、顯示和動(dòng)畫。
3)所屬框架不同。UIView類是屬于UIKit.framework框架的,UIKit框架主要就是用來構(gòu)建用戶界面的。CALayer類是屬于QuartzCore.framework框架的,而且CALayer是作為一個(gè)低級(jí)的,可以承載繪制內(nèi)容的底層對(duì)象出現(xiàn)在該框架的。
2.
為什么iOS中提供UIView和CALayer這兩個(gè)平行的層級(jí)結(jié)構(gòu)呢?正確答案:iOS中提供UIView和CALayer這兩個(gè)平行層級(jí)結(jié)構(gòu)主要是為了做到職責(zé)分離,實(shí)現(xiàn)視圖的繪制、顯示和布局解耦,避免很多重復(fù)的代碼。在iOS和MacOS兩個(gè)平臺(tái)上,事件和用戶交互有很多地方并不相同,畢竟基于多點(diǎn)觸控的用戶界面和基于鼠標(biāo)鍵盤有著本質(zhì)的區(qū)別,這就是為什么iOS有UIKit和UIView,但是MacOS有Appkit和NSView的原因。它們功能雖然相似,但是在實(shí)現(xiàn)上有著顯著的區(qū)別。創(chuàng)建兩個(gè)層次結(jié)構(gòu)就能夠在iOS與MacOS之間共享代碼,從而使得開發(fā)更加便捷。
3.
UIWindow是什么?有什么特點(diǎn)和作用?正確答案:從下圖中的繼承關(guān)系會(huì)發(fā)現(xiàn)UIWindow居然是UIView的子類,因?yàn)閁IWindow在應(yīng)用中是作為根視圖來承載UIViewr元素的,也就是說根父視圖是子視圖的子類,有點(diǎn)違背直覺。
CALayer和UIView繼承關(guān)系
但事實(shí)就是這樣,UIWindow提供一個(gè)區(qū)域(一般就是整個(gè)屏幕)來顯示UIView,并且將事件分發(fā)給UIView。一個(gè)應(yīng)用一般只有一個(gè)UIWindow,但特殊情況也會(huì)創(chuàng)建子UIWindow,例如實(shí)現(xiàn)一個(gè)始終漂浮在頂層的懸浮窗,就可以使用一個(gè)UIWindow來實(shí)現(xiàn)。
4.
什么是Layer層對(duì)象?正確答案:Layer層對(duì)象是用來展示可見內(nèi)容的一種數(shù)據(jù)對(duì)象,常在視圖中用來渲染視圖內(nèi)容。一般的層對(duì)象在界面中可以實(shí)現(xiàn)一些復(fù)雜的動(dòng)畫或者其他類型的一些復(fù)雜特效。
常見的幾個(gè)其自身具有繪制功能的專用Layer有:CATextLayer、CAShapeLayer、CAGradientLayer,這里給出使用示例。其他還有用于3D圖形變換的CATransformLayer,實(shí)現(xiàn)滾動(dòng)視圖的CAScrollLayer,專門播放視頻的AVPlayerLayer和制作粒子特效的CAEmitterLayer等。它們都是繼承自CALayer的,和CALayer一樣都來自QuartzCore.framework框架。
1.CATextLayer
這個(gè)類是用來實(shí)現(xiàn)更加靈活的文字布局和渲染的,它幾乎包含了UILabe1的所有特性并在此基礎(chǔ)上增加了很多更強(qiáng)大的功能,包括字體、尺寸、前景色和下畫線等文字效果,同時(shí)CATextLayer的渲染效率明顯高于UILabel。
通過CALayer來實(shí)現(xiàn)一個(gè)UILabel的示例代碼如下(效果見圖):
-(void)viewDidLoad{
[superviewDidLoad];
/*創(chuàng)建一個(gè)字符承載視圖*/
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
這個(gè)類是用來專門繪制矢量圖形的圖形子類,例如可以指定線寬和顏色等利用CGPath繪制圖形路徑,可以實(shí)現(xiàn)圖形的3D變換效果,渲染效率比CoreGraphics快很多,而且可以在超出視圖邊界之外繪制,即不會(huì)被邊界裁減掉。
這里展示使用CAShapeLayer繪制一個(gè)圓形的實(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
它是一個(gè)硬件加速的高性能繪制圖層,主要用來實(shí)現(xiàn)多種顏色的平滑漸變效果。這里給出一個(gè)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繪制效果
5.
如何使用CAShapeLayer繪制圖層?正確答案:CAShapeLayer是一個(gè)通過矢量圖形來進(jìn)行繪制的圖層子類。開發(fā)者通過指定諸如顏色和線寬等屬性,用CGPath來定義指定形狀的圖形,最后CAShapeLayer對(duì)象就會(huì)自動(dòng)渲染出來了。與直接使用CoreGraphics在原始的CALayer對(duì)象中繪制的方式相比,使用CAShapeLayer有以下優(yōu)點(diǎn):
1)渲染速度更快。CAShapeLayer使用了硬件加速的方式繪制圖形,繪制速度比用CoreGraphics快很多。
2)內(nèi)存使用更加高效。普通的CALayer對(duì)象需要?jiǎng)?chuàng)建一個(gè)寄宿圖,而CAShapeLayer不需要,這樣就節(jié)約了內(nèi)存。
3)不會(huì)被邊界圖層裁剪掉。一個(gè)CAShapeLayer可以在圖層邊界繪制。CAShapeLayer的圖層路徑不會(huì)像在使用CoreGraphics的普通CALayer一樣被裁剪掉。
通常通過指定CAShapeLayer對(duì)象的path屬性來繪制圖層。代碼如下:
@property(nullable)CGPathRefpath;
此外還可以通過一些屬性來描繪形狀的線條,例如lineWidth屬性用于設(shè)置線寬,lineCap屬性用于描繪線條結(jié)尾的樣子,但是在圖層層面只有一次機(jī)會(huì)設(shè)置這些屬性。如果想用不同顏色或風(fēng)格來繪制多個(gè)形狀,那么就不得不為每個(gè)形狀準(zhǔn)備一個(gè)圖層。下面示例使用CAShapeLayer渲染一個(gè)簡單的多邊形,由于CAShapeLayer對(duì)象的path屬性是CGPathRef類型,所以很容易使用UIBezierPath類幫助創(chuàng)建圖層路徑,這樣就不需要人工釋放CGPath了。代碼如下:
/*創(chuàng)建一個(gè)CAShapeLayer對(duì)象*/
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對(duì)象*/
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繪制的路徑圖
6.
iOS中如何實(shí)現(xiàn)為UIImageView添加圓角?正確答案:圓角指按照一定圓角半徑平滑矩形視圖的4個(gè)角的效果,如圖所示。
圓角效果
按照背后的渲染方式,實(shí)現(xiàn)UIView及其子類的圓角效果有兩種方法:一種是直接設(shè)置layer的圓角屬性,為“離屏渲染”;另一種是自定義圓角繪制方法,實(shí)現(xiàn)“當(dāng)前屏幕渲染”。
當(dāng)前屏幕渲染(On-screenRendering)指GPU直接在當(dāng)前顯示的屏幕緩沖區(qū)中進(jìn)行圖形渲染,不需要提前另開緩沖區(qū)也就不需要緩沖區(qū)的切換,因此性能較高。
離屏渲染(Off-screenRendeiing):簡單來說就是提前另開一個(gè)緩沖區(qū)進(jìn)行圖形渲染,由于顯示需要和當(dāng)前屏幕緩沖區(qū)進(jìn)行切換,所以很耗費(fèi)性能。通常圓角、遮罩、不透明度、陰影、漸變、光柵化和抗鋸齒等設(shè)置都會(huì)觸發(fā)離屏渲染。
(1)“離屏渲染”實(shí)現(xiàn)圓角
iOS中圓角效果實(shí)現(xiàn)的最簡單、最直接的方式是直接修改View的layer層參數(shù),這樣會(huì)觸發(fā)“離屏渲染”,性能不高。
/*設(shè)置圓角半徑*/
view.layer.cornerRadius=5;
/*將邊界以外的區(qū)域遮蓋住*/
view.layer.masksToBounds=YES;
(2)“當(dāng)前屏幕渲染”實(shí)現(xiàn)圓角
直接在當(dāng)前屏幕渲染繪制,提高性能。
為UIImage類擴(kuò)展一個(gè)實(shí)例方法:
/*On-screen-renderring繪制UIImage矩形圓角*/
-(UIImage*)imageWithComerRadius:(CGFloat)radiusofSize:(CGSize)size{
/*當(dāng)前UIImage的可見繪制區(qū)域*/
CGRectrect=(CGRect){0.f,0.f,size};
/*創(chuàng)建基于位圖的上下文*/
UIGraphicsBeginImageCoritextWithOptions(size,NO,UIScreen.mainScreen.scale);
/*在當(dāng)前位圖上下文添加圓角繪制路徑*/
CGContextAddPath(UIGraphicsGetCurrentContext0,[UIBezierPathbezierPathWithRoundedRect:rectcomerRadius:radius].CGPath);
/*當(dāng)前繪制路徑和原繪制路徑相交得到最終裁剪繪制路徑*/
CGContextClip(UIGraphicsGetCurrentContext());
/*繪制*/
[selfdrawInRect:rect];
/*取得裁剪后的image*/
UIImage*image=UIGraphicsGetImageFromCurrentImageContext();
/*關(guān)閉當(dāng)前位圖上下文*/
UIGraphicsEndImageContext();
returnimage;
}
使用時(shí),讓實(shí)例化的UIImage對(duì)象調(diào)用上面的實(shí)例方法即可。
UIImageView*imageView=[[UIImageViewalloc]initWithFrame:CGRectMake(10,10,100,100)];
/*創(chuàng)建并初始化UIImage*/
UIImage*image=[UIImageimageNamed:@"icon"];
/*添加圓角矩形*/
image=[imageimageWithComerRadius:50ofSize:imageView.frame.size];
[imageViewsetImage:image];
7.
contentsScale屬性有什么作用?正確答案:圖層的contentsScale屬性屬于支持高分辨率屏幕(如Retina屏幕)機(jī)制的一部分,它定義了圖層content中圖像的像素尺寸與視圖大小的比例。它也被用來判斷在繪制圖層時(shí)允許為content屬性創(chuàng)建的空間大小,以及需要顯示的圖片的拉伸度。
默認(rèn)情況下,contentsScale的值是1.0,也就是說圖層的繪制系統(tǒng)將會(huì)以每個(gè)點(diǎn)對(duì)應(yīng)一個(gè)像素來繪制圖片。如果將其設(shè)置為2.0,那么會(huì)以每個(gè)點(diǎn)對(duì)應(yīng)兩個(gè)像素來繪制圖片,此即所謂的Retina屏幕。
在開發(fā)中,有時(shí)會(huì)直接為圖層的content設(shè)置圖片,這時(shí)可以設(shè)置contentsScale為合適的值,以防止圖片在Retina屏幕上顯示不正確(像素化或模糊),代碼如下:
layer.contentsScale=[UIScreenmainScreen].scale;
8.
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)并不會(huì)用于屏幕布局,但是仍然和圖片有相對(duì)關(guān)系。UIImage是一個(gè)屏幕分辨率解決方法,它是用點(diǎn)來度量大小的。但是,一些底層的CGImage類型的圖片會(huì)使用像素,所以必須清楚在Retina設(shè)備和普通設(shè)備上,點(diǎn)和像素代表著不同的大小。
9.
如何理解anchorPoint和position的作用?正確答案:在UIView中有3個(gè)比較重要的布局屬性:frame、bounds和center,它們分別對(duì)應(yīng)于CALayer中的frame、bounds和position。雖然圖層使用position,而視圖使用了center,但是這兩個(gè)屬性都代表了同樣的值,即當(dāng)前圖層的anchorPoint點(diǎn)相對(duì)于父圖層的位置。
anchorPoint被稱為“錨點(diǎn)”。圖層的anchorPoint屬性通過影響position的值來控制它的frame,可以將anchorPoint比作控制圖層移動(dòng)的“支點(diǎn)”。anchorPoint是使用單位坐標(biāo)來描述的,也就是圖層的相對(duì)坐標(biāo),圖層左上角是{0,0},右下角是{1,1}。anchorPoint默認(rèn)的坐標(biāo)是{0.5,0.5},即圖層的中心點(diǎn)。
position等價(jià)于視圖中的center,它代表了anchorPoint點(diǎn)在父圖層(superLayer)的位置。因此可以說,position點(diǎn)是相對(duì)于父圖層坐標(biāo)系的,而anchorPoint是相對(duì)于當(dāng)前圖層的,兩者是相對(duì)于不同的坐標(biāo)系的一個(gè)重合點(diǎn)。
事實(shí)上,position和anchorPoint的值是互不影響的,也就是說修改其中任何一個(gè)的值,另外一個(gè)的值不會(huì)改變,改變的只是當(dāng)前圖層的frame。對(duì)于視圖或者圖層來說,frame并不是一個(gè)非常清晰的屬性,它其實(shí)是一個(gè)虛擬屬性,是根據(jù)bounds、position和transform計(jì)算而來的,當(dāng)其中任何一個(gè)值發(fā)送改變時(shí),frame都會(huì)變化。相反,改變frame的值同樣也會(huì)影響它們的值。frame、position和anchorPoint的關(guān)系可以用如下公式表達(dá):
frame.origin.x=position.x-anchorPoint.x*bounds.size.width;
frame.origin.y=position.y-anchorPoint.y*bounds.size.height;
在制作動(dòng)畫時(shí),視圖默認(rèn)是圍繞中心點(diǎn)進(jìn)行旋轉(zhuǎn)或平移的,這是因?yàn)槟J(rèn)UIView的rootLayer的anchorPoint就是圖層的中心。在實(shí)際開發(fā)中,可能需要改變anchorPoint以達(dá)到其他的效果,如下示例代碼演示了類似于播放器的效果(界面見圖)。當(dāng)單擊屏幕時(shí),臂桿能夠圍繞頂部旋轉(zhuǎn),storyboard中的代碼如下:
/*控制器代碼如下*/
@interfaceAnimation(){
__weakIBOutletUIImageView*_needle;
BOOL_playing;//設(shè)置一個(gè)布爾值來控制下降或上升
}
@end
@implementationAnimation
-(void)viewDidLoad{
[superviewDidLoad];
}
-(void)viewDidAppear:(BOOL)animated{
[superviewDidAppear:animated];
/*改變視圖的錨點(diǎn)和position*/
/*如果僅僅改變錨點(diǎn),那么_needle視圖將會(huì)下移*/
_needle.layer.anchorPoint=CGPointMake(0.5,0);
needle.layer.position=CGPointMake(needle.superview.frame.size.width*0.5,0);
_needle.transform=CGAffineTransformRotate(_needle.transform,M_PI/12);
}
/*單擊屏幕,移動(dòng)臂桿*/
/*當(dāng)然也可以添加一些動(dòng)畫,使得臂桿的動(dòng)作更自然,但此處主要是為了演示anchorPoint和position的作用*/
-(void)touchesBegan:(NSSet<UITouch*>*)toucheswithEvent:(UIEvent*)event
if(!_playing){
_needle.transform=CGAffineTransformIdentity;
}else{
_needle.transform=CGAffineTransformRotate(_needle.transform,M_PI/12);
}
_playing=!_playing;
}
播放器效果
10.
如何理解drawRect:方法?正確答案:iOS的繪圖操作是發(fā)生在UIView類的drawRect:方法中的。如果想在UIView中繪圖,那么可以通過繼承UIView類并實(shí)現(xiàn)其drawRect:方法,在drawRect:方法中獲取當(dāng)前的環(huán)境上下文(context)進(jìn)行繪制。drawRect:方法被定義在UIView的UIViewRendering類別中:
-(void)drawReet:(CGRect)rect;
drawRect:里面的代碼利用CoreGraphics在指定的rect中繪制圖形,然后內(nèi)容就會(huì)被緩存起來直到它需要被更新。事實(shí)上,蘋果公司并不建議開發(fā)者主動(dòng)調(diào)用drawRect:方法,當(dāng)然如果強(qiáng)制直接調(diào)用該方法,那么也是沒有效果的,因?yàn)橄到y(tǒng)此時(shí)不會(huì)自動(dòng)創(chuàng)建和View相關(guān)聯(lián)的上下文。而且當(dāng)沒有自定義繪制任務(wù)時(shí),就不要在子類中寫一個(gè)空的drawRect:,否則會(huì)造成CPU資源和內(nèi)存的浪費(fèi)。
當(dāng)視圖在屏幕中出現(xiàn)的時(shí)候,drawRect:方法就會(huì)被自動(dòng)調(diào)用。具體是,drawRect:方法的第一次調(diào)用是在控制器中l(wèi)oadView和viewDidLoad兩方法之后。所以不必?fù)?dān)心在控制器初始化之前,drawRect:就會(huì)被執(zhí)行。雖然drawRect:是UIView類中的方法,但事實(shí)上都是底層的CALayer對(duì)象安排了重繪工作并保存了繪制好的內(nèi)容。
另外,可以調(diào)用setNeedsDisplay:方法將繪制好的圖形更新到視圖上。setNeedsDisplay:方法就是在receiver上設(shè)置一個(gè)需要被重新繪制的標(biāo)記,在下一個(gè)繪制周期自動(dòng)進(jìn)行重繪,一般iPhone的刷新頻率為60Hz,也就是說1/60s后重繪。示例代碼如下:
-(void)drawRect:(CGRect)rect{
/*獲取上下文*/
CGContextRefctx=UIGraphicsGetCurrentContext();
/*繪制一個(gè)圓形*/
CGContextAddEllipseInRect(ctx,CGRectMake(0,0,200,200));
/*設(shè)置顏色*/
[[UIColorredColor]set];
/*填充*/
CGContextFillPath(ctx);
}
11.
如何使用mask屬性實(shí)現(xiàn)圖層蒙版功能?正確答案:在實(shí)際開發(fā)中,通常使用mask屬性來實(shí)現(xiàn)圖層蒙版的功能。這個(gè)屬性本身就是CALayer類型,它和其他圖層一樣擁有繪制和布局的屬性。但不同于那些繪制在父圖層中的子圖層,mask圖層定義了父圖層的部分可見區(qū)域。
mask圖層中最重要的是圖層的輪廓,在父圖層中,與mask圖層相重疊的部分將被保留,其他的部分將被遮蓋。也就是說,父圖層提供內(nèi)容,而mask圖層提供形狀。事實(shí)上,mask圖層不僅僅局限于靜態(tài)圖,還可以使用代碼或者動(dòng)畫實(shí)時(shí)地生成。
示例代碼如下:
-(void)viewDidLoad{
[superviewDidLoad];
/*設(shè)置寄宿圖*/
self.view.layer.contents=(id)[UIImageimageNamed:@"海水"].CGImage;
/*設(shè)置寄宿圖的顯示模式,等價(jià)于UIView的contentMode*/
self.view.layer.contentsGravity=@"resizeAspect";
/*設(shè)置mask層*/
UIImageView*searchImageView=[[UIImageViewalloe]initWithFrame:CGRectMake(([UIScreenmainScreen].bounds.size.width-150)*0.5,([UIScreenmainScreen].bounds.size.height-150)*0.5,150,150)];
searchImageView.image=[UIImageimageNamed:@"馬"];
self.view.layer.mask=searchImageView.layer;
}
代碼執(zhí)行的效果如圖所示。
圖層蒙版效果
12.
如何解決masksToBounds離屏渲染帶來的性能損耗?正確答案:在開發(fā)中常通過CALayer的cornerRadius屬性來設(shè)置圖層的圓角曲率(如設(shè)置圓角圖片)。默認(rèn)情況下,cornerRadius只影響背景顏色而不影響背景圖片或子圖層。但當(dāng)將CALayer的masksToBounds設(shè)置為YES時(shí),圖層的內(nèi)容就會(huì)被截取。代碼如下:
imageView.layer.cornerRadius=10
imageView.layer.masksToBounds=YES
由于這樣處理的渲染機(jī)制是GPU在當(dāng)前屏幕緩沖區(qū)外新開辟的一個(gè)渲染緩沖區(qū)進(jìn)行工作,也就是所謂的離屏渲染,所以這會(huì)給應(yīng)用程序帶來額外的性能損耗。如果在某一時(shí)刻大量地使用這種方式設(shè)置圓角,那么就會(huì)觸發(fā)緩沖區(qū)頻繁合并和上下文之間的頻繁切換,這時(shí)應(yīng)用程序就有可能出現(xiàn)掉幀和卡頓。具體可以使用Xcode自帶的Instruments(工具)進(jìn)行檢測。
為了防止因離屏渲染而產(chǎn)生性能損耗,可以不使用CALayer的cornerRadius和masksToBounds屬性,而將處理圖片的權(quán)利交于CPU,雖然CPU對(duì)圖形的處理能力不及GPU,但設(shè)置圓角圖片的處理難度并不大,且代價(jià)遠(yuǎn)小于上下文切換。以下是實(shí)際開發(fā)中常用的兩種優(yōu)化方案:
1)使用CALayer提供的shouldRasterize屬性。shouldRasterize屬性是設(shè)置光柵化,可以使離屏渲染的結(jié)果緩存到內(nèi)存中存為位圖,當(dāng)下次
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 術(shù)中大出血急救護(hù)理
- 腸炎驚厥疾病查房要點(diǎn)解析
- 部編人教版三年級(jí)語文下冊(cè)《守株待兔》示范公開課教學(xué)課件(第1課時(shí))
- 新生兒心律失常護(hù)理措施
- 新生兒沐浴健康教育
- 新生兒用藥指導(dǎo)
- 服裝設(shè)計(jì)公司介紹
- DB32/T 4612-2023消費(fèi)品缺陷調(diào)查工作規(guī)范
- 無錫游戲外設(shè)項(xiàng)目商業(yè)計(jì)劃書
- 2025年有機(jī)護(hù)膚品市場銷售渠道變革與線上線下融合報(bào)告
- 國際壓力性損傷-潰瘍預(yù)防和治療臨床指南(2025年版)解讀
- 重慶市機(jī)動(dòng)車維修工時(shí)定額標(biāo)準(zhǔn)
- 新能源汽車傳動(dòng)系統(tǒng)高端智能設(shè)備研發(fā)和生產(chǎn)項(xiàng)目環(huán)評(píng)資料環(huán)境影響
- 湖北省2024年本科普通批錄取院校(首選歷史)平行志愿投檔線
- 鋁錠生產(chǎn)工藝流程
- 艾灸師(高級(jí))職業(yè)技能競賽考試題庫
- 《心臟驟停的急救護(hù)理》課件
- 做最勇敢的自己
- 2024年歷年江西農(nóng)商銀行員工招聘筆試真題
- 人工智能賦能科研管理
- 2025版亞馬遜FBA物流配送及電商運(yùn)營服務(wù)合同3篇
評(píng)論
0/150
提交評(píng)論