前言
一直想研究的问题,一直不知道怎么研究的一个问题,直到看到了CRT....算大致了解了一些。
问题
一个控件想要显示在屏幕上我们知道用UIView或者其子类都可以实现,但是它为什么会显示在屏幕上?或者它显示在屏幕上之前都做了什么?
其实UIView能显示在屏幕上离不开CALayer的支持,CALayer又是什么?为什么单独的UIView就不行?其实UIView是个容器,CALayer是负责绘制,绘制完成交给UIView去显示。为什么?为什么不让CALayer直接去显示?
那么我就想知道为什么手机屏幕可以显示这些图像?
刨根问底的问题不能说没有意义(要适当),只是没有去研究它的原理。下面笔者会大致
的介绍一下显示器成像的原理和iOS应用添加一个View为什么可以在屏幕上显示。(粗略回答,如有错误,感谢您指出。😁)
正常我们身边接触到的显示器屏幕,大致可分为CRT,LCD,OLED,(笔者对硬件是一片空白,能说出这些已经很不错了。 )
CRT
学名为:阴极射线显像管,我们主要来介绍它的成像原理。CRT显示器能成像的基础是靠电子束激发屏幕内表面的荧光粉来显示的,电子束我们通常可以叫做电子枪,荧光粉按照一定的方式涂在荧光屏上密密麻麻的排列为红绿蓝(RGB)三种颜色的荧光粉条称为荧光粉单元,我们通常称为这一个单元为一个像素,这样大家理解像素的意思了吧。电子枪的工作原理笔者完全看不懂里面的介绍,毕竟术业有专攻,大致上是说,通电之后灯丝加热,阴极发射电子,电击枪以极高的速度去轰击这些荧光粉层,受到这些轰击像素受到电脑显卡R,G,B三个基色视频信号的控制,来显示强弱色,以此我们才看到了这些丰富多彩的画面。
电子枪有多种扫描方式,介绍一种:逐行扫描,就是一行一行从左到右的扫描,所以不但电子枪要有横向移动的能力,还要有纵向和斜向的移动。当从左到右然后换行一直到最后成为一帧,肉眼看起来不卡顿至少要30帧以上,意思就是每秒电子枪要这样循环扫描30次以上。
在iPhone8plus上分辨率为1920*1080=2073600,就是有大约200万个像素点,所以你知道电子枪得有多辛苦,当然CRT这种成像现在的iphone并没有用,但是都是基于三基色RGB去成像的 。
LCD
LCD简称液晶屏,它的原理和CRT不同的是他没有荧光粉,而是利用了彩色滤色片,彩色滤色片就是RGB组成的,然后在它上面是偏光板,偏光板的作用就是把这些颜色呈现明暗,然后我们肉眼看到的就是不同的颜色。LCD的显示器的每个点都能接收到信号,不需要电子枪逐行的扫描。
OLED
技术越先进越不好理解,在网上查找的大致是这样的,它和LCD不同的是,LCD需要背光板发光映射给彩色滤色片,而OLED不需要背光板,三基色单元本身就会发光(⊙︿⊙),感受到了被技术支配的恐惧。好啦, 大致就是这些。
好吧,实在是编不下去了,但是成像原理确实是这样。所以理解我们的iOS应用为什么能成像,我们只要知道CRT原理就好了,至少还能看懂些,LCD和OLED借助的是高/低分子材料,已经涉及到化学了,所以刨根问底适当为止。
底层
为什么我们写一个UIView会显示在屏幕上?
当我们用代码在Xcode上self.view.addSubView(view1)
然后点击Run,经过编译,链接生成可执行文件,模拟器被打开,屏幕过渡动画到显示到我们的眼前。
其中显示这个环节是这样的:我们运行这个程序,CPU会计算好所有的要显示的内容(CPU是做复杂计算和处理的中央处理器)然后交给GPU(GPU主要负责单一重复运算,最主要是做图形方面的渲染),GPU渲染后将渲染结果放入帧缓冲区,随后视频控制器会逐行读取帧缓冲区的数据,经过一通我们不懂得操作传递给显示器显示。
iOS应用
iOS里,最上层是有SDK提供给我们的UIKit框架去搭建我们的UI,我们通过这个框架能搭建出任意我们想要的页面,在它下层支持的是CoreAnimation,CoreAnimation是iOS能显示控件的核心,iOS所有的控件几乎都是CoreAnimation的封装,或者是直接的使用CoreAnimation,CoreAnimation的在下一层是有Metal和CoreGraphics支持,他们由OpenGL/OpenGL ES支持,OpenGL/OpenGL ES不是太了解,但是他们应该是离硬件最近的了。 苹果官方并没有贴出关于OpenGL/OpenGL ES的东西,可能是因为他们要大力推广Metal的原因。
为什么单独的UIView不能显示?
因为UIView只是一个呈现CALayer的容器,CALayer没有显示的功能,他要借助UIView这个容器,所以他们是相辅相成的关系。UIView设置的background
,frame
,等等其实都是给CALayer设置的,可以说UIView只是在CALayer上套了一个壳子。下面我会猜测一下为什么要这样。
为什么不让CALayer直接去显示?
这个问题也没有标准答案,只能是猜测吧.我们打开CALayer的.h文件我们会发现基本上所有的定义的属性和函数都是iOS2.0之后的,所以猜测可能在2.0之前确实使用CALayer去实现单独显示的,但是iOS2.0之后,由于业务功能的扩展,CALayer越来越大,所以就不能承担多业务的能力,所以对每种业务都有不同的它的封装去实现,这个应该是就做策略模式。
/** The base layer class. **/
@available(iOS 2.0, *)
open class CALayer : NSObject, NSSecureCoding, CAMediaTiming
<UILabel: 0x7fdf605092e0; frame = (0 100; 100 30); text = '123456'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60000028c760>>
<_UILabelLayer:0x60000028c760; position = CGPoint (50 115); bounds = CGRect (0 0; 100 30); delegate = <UILabel: 0x7fdf605092e0; frame = (0 100; 100 30); text = '123456'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60000028c760>>; allowsGroupOpacity = YES; contentsMultiplyColor = (null); rasterizationScale = 3; contentsScale = 3>
上面这段代码我们可以看到CALayer会把UILable隐式的修改为_UILabelLayer
。
参考文献:
Core Animation Programming Guide
CRT显示器
LCD显示器
OLED如何成像原理
总结的不好,请谅解。如有错误,请您指正。感谢。