屏幕显现的原理-体系层面
首要,咱们看无聊看动态的视频看静态的画面,手机都会以特定的频率改写当时界面,120HZ便是每秒120帧画面,60HZ便是每秒60帧画面,画面是由点组成的,分辨率便是具体的点数。而显现设备要做的便是计算各个像素点的显现数值,并把它显现在屏幕上。那么大致的流程是怎么样的呢?
上图是iOS 烘托结构组成部分,其间UIKit坐落最上层,组成界面的各个元素基本上都来自UIKit,咱们可以给它设置布局,可以通过制作改变它的显现内容,除此之外还负责事件的接收,其实界面的显现是由它的一个被称为图层的特点CALayer来完结的。这个放在后面具体介绍。UIKit的下一层是Core Animation,最开始触摸iOS的时分,我一向认为Core Animation仅仅用于生成动画的,实际上动画的生成仅仅Core Animation的冰山一角,可以说在iOS上绝大多数的原生控件都是通过Core Animation制作出来的,Core Animation在这儿最重要的使命是尽可能快地组成图层送到下一级。坐落Core Animation之下是Open GL 以及 Core Graphic,其间Open GL 运用GPU进行烘托,而Core Graphic则是运用Qurtaz 2D引擎运用CPU进行烘托,这儿个人理解Core Graphic不单单只有CPU参加,最终烘托到屏幕上仍是需求GPU参加,这部分在下个小结中将会进行具体介绍,各个GPU厂商的完成是不同的,为了阻隔这个不同,在GPU的上层添加了GPU驱动层,通过GPU处理后的数据会放到帧缓冲区中,最终显现到显现器上。
屏幕显现的原理-iOS开发视点
咱们都知道,iOS开发中,有个UIKit结构,而其间的UIView及其子类,咱们开发者过程中基本会用这些来做咱们的业务画面。UIView中有个特点,叫layer,对象类型为CALayer,也称之为纹路。layer有个id类型的特点contents,它指向内存中的一个成为backing storage的存储空间。往contents上赋值的时分就会将图片存储到这个backing storage中,这儿虽然是id类型,可是假如传递其他类型进去会不显现,这儿为什么运用id类型而不是清晰的CGImageRef,也仍是为了兼容,由于图像类型在Mac OS中是NSImage类型而在iOS上却是CGImageRef类型。
隐式动画是Core Animation结构主动完结的动画,不需求咱们手动操控。支持隐式动画的CALayer特点叫Animatable Properties
显式动画允许你对一些特点做指定的自定义动画,或创立非线性动画,比方沿着任意一条曲线移动
业务上,你总是要制作一些图形,自定义一些视图,一般咱们运用CoreAnimation结构和CoreGraphics结构。 CoreAnimation结构以及API CoreGraphics结构以及API
离屏烘托: 上面介绍的烘托为当时屏幕烘托(On-Screen Rendering),也便是GPU的操作是在当时用于显现的屏幕缓冲区中进行的,可是还有一种烘托模式为离屏烘托,它发生在某些图层元素未预先组成之前不能直接在当时屏幕上制作的状况下,这种状况下体系会新开一个缓冲区,在这儿进行烘托操作。
离屏烘托一般发生在如下几种状况:
-
shouldRasterize = YES(敞开光栅化)
-
edge antialiasing(抗锯齿)
-
group opacity(透明度)
-
circleRadius (圆角)
-
masks(遮罩)
-
shadows(暗影)
知道原理和用法之后,平常开发中应该留意什么呢?
1.自定义视图的时分,尽量别写drawRect方法,由于drawRect: 方法没有默许的完成,假如咱们在UIView中完成了drawRect方法,就算它的函数体内部实际没有代码,体系也会为这个view申请一块内存区域,等候CoreGraphics可能的绘画操作。 只有当自定义控件中有特殊的图案时,才主张完成drawRect:进行制作。
2.为了防止离屏缓存,图片的圆角不要直接用layer.cornerRadius设置,用CoreGraphics进行设置图片的圆角。
@interface UIImage(YYPClip)
* (UIImage \*)drawCircleImage;
@end
@implementation UIImage(YYPClip)
* (UIImage \*)drawCircleImage {
CGFloat side = MIN(self.size.width, self.size.height);
UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), false, \[UIScreen mainScreen].scale);
CGContextAddPath(UIGraphicsGetCurrentContext(),
\[UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, side, side)].CGPath);
CGContextClip(UIGraphicsGetCurrentContext());
CGFloat X = -(self.size.width - side) / 2.f;
CGFloat Y = -(self.size.height - side) / 2.f;
\[self drawInRect:CGRectMake(X, Y, self.size.width, self.size.height)];
CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
UIImage \*output = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return output;
}
@end
//在需求圆角时调用如下
dispatch\_async(dispatch\_get\_global\_queue(DISPATCH\_QUEUE\_PRIORITY\_DEFAULT, 0), ^{
UIImage \*img = \[\[UIImage imageNamed:@"order"] drawCircleImage];
dispatch\_async(dispatch\_get\_main\_queue(), ^{
view\.image = img;
});
});
3.防止离屏烘托
延伸阅览与参阅链接
iOS-烘托体系作业原理介绍
制作像素到屏幕上
关于iOS离屏烘托的深入研究