【译】About Drawing and Printing in iOS

优势和限制


自定义UI提供能更大的绘制灵活性

自定义UI是计算密集型操作,不能充分利用GPU,所以尽可能少的使用本地图形绘制技术。

Depending on the type of app you are creating, it may be possible to use little or no custom drawing code. Although immersive apps typically make extensive use of custom drawing code, utility and productivity apps can often use standard views and controls to display their content.

是否需要自己绘制UI取决于创建的App类型,很可能只需要使用很少或者不使用绘制代码。尽管有一些场景必须使用自定义绘制代码,但是它们的内容通常仍然可以用标准视图和控件显示。

The use of custom drawing code should be limited to situations where the content you display needs to change dynamically. For example, a drawing app typically needs to use custom drawing code to track the user’s drawing commands, and an arcade-style game may need to update the screen constantly to reflect the changing game environment. In those situations, you should choose an appropriate drawing technology and create a custom view class to handle events and update the display appropriately.

在显示需要动态改变的内容时,应该尽可能少的使用自定义绘制代码。这种情况下应该选择合适的绘制技术,并创建一个自定义view用来处理事件和更新显示内容。

On the other hand, if the bulk of your app’s interface is fixed, you can render the interface in advance to one or more image files and display those images at runtime using theUIImageViewclass. You can layer image views with other content as needed to build your interface. You can also use theUILabelclass to display configurable text and include buttons or other controls to provide interactivity. For example, an electronic version of a board game can often be created with little or no custom drawing code.

如果你的app需要显示的内容是固定的,你可以预先将这些内容输入到图像文件并使用UIImageView来显示。

Because custom views are generally more processor-intensive (with less help from the GPU), if you can do what you need to do using standard views, you should always do so. Also, you should make your custom views as small as possible, containing only content that you cannot draw in any other way, use use standard views for everything else. If you need to combine standard UI elements with custom drawing, consider using a Core Animation layer to superimpose a custom view with a standard view so that you draw as little as possible.

因为自定义视图通常是计算密集型操作,(较少的获得GPU的协助),能使用标准视图的情况下尽量使用标准视图。尽可能少的使用自定义视图。如果需要在标准视图上绘制自定义内容,可以考虑使用Core Animation layer叠加在标准视图上面,这样就可以较少的使用自定义绘制代码。

关键概念和理论


For thedrawRect:method, UIKit creates agraphics contextfor rendering to the display. This graphics context contains the information the drawing system needs to perform drawing commands, including attributes such as fill and stroke color, the font, the clipping area, and line width. You can also create and draw into custom graphics context for bitmap images and PDF content.

UIKit创建一个图形上下文(graphics context)用于呈现内容,graphics context包括绘制系统执行绘制命令的信息,包括填充属性、绘制颜色、字体、剪切区域、线宽等等。你也可以在自定义图形上下文创建和绘制位图及PDF。

UIKit has adefault coordinate systemwhere the origin of drawing is at the top-left of a view; positive values extend downward and to the right of that origin. You can change the size, orientation, and position of the default coordinate system relative to the underlying view or window by modifying the current transformation matrix, which maps a view’s coordinate space to the device screen.

UIKit默认的坐标系统,起点是左上角

In iOS, thelogical coordinate space, which measures distances in points, is not equal to the device coordinate space, which measures in pixels. For greater precision, points are expressed in floating-point values.

逻辑坐标空间是以点为单位的,不同于设备以像素为单位的坐标系统。为了更大的精确度,点坐标用浮点数表示。

iOS Drawing Concepts

Important:Not all UIKit classes are thread safe. Be sure to check the documentation before performing drawing-related operations on threads other than your app’s main thread.

The UIKit Graphics System

所有绘制都是在UIView和它的子类中。UIView定义了绘制发生在屏幕的哪一个部分(确定绘制区域)。如果用系统提供的View,绘制区域这个已经自动处理好了。

离屏绘制位图或者PDF上下文时,并不是在一个UIView中绘制,也就意味着关于绘制的部分概念是不适用的,例如The View Drawing Cycle。

The View Drawing Cycle

当view第一次显示或者view的某个区域需要重新绘制时,回调用view的drawRect:方法

以下几种情况会触发view更新:

1、移入/移除一个view遮盖住当前view

2、一个预先隐藏的view,设置器hidden属性为NO

3、把一个离屏的view又回到屏幕

4、在view中显示的调用setNeedsDisplayorsetNeedsDisplayInRect:方法

系统View是自动管理重绘的。

自定义View,需要重写drawRect:方法,并在这个方法内执行所有的绘制代码。

The first time your view becomes visible, iOS passes a rectangle to the view’sdrawRect:method that contains your view’s entire visible area.

当自定义View第一次变得可见时,iOS会发送一个矩形给View的drawRect:方法,这个矩形包括View所有的可见区域。

During subsequent calls, the rectangle includes only the portion of the view that actually needs to be redrawn.

在之后的调用中,这个矩形只包含实际重绘的区域。

如果希望刷新View的内容,调用setNeedsDisplayorsetNeedsDisplayInRect:方法触发重绘。

不要自行调用drawRect:方法,这个方法只能由系统再次绘制的代码自动调用。因为在其他的时候,并不存在图形上下文,所以不能绘制。

Coordinate Systems and Drawing in iOS

The drawing (user) coordinate system. This coordinate system is used when you issue drawing commands.

The view coordinate system (base space). This coordinate system is a fixed coordinate system relative to the view.

The (physical) device coordinate system. This coordinate system represents pixels on the physical screen.

Each view also has acurrent transformation matrix (CTM), a mathematical matrix that maps the points in the current drawing coordinate system to the (fixed) view coordinate system. The app can modify this matrix (as described later) to change the behavior of future drawing operations.

An upper-left-origin coordinate system (ULO),The default coordinate system used by the UIKit and Core Animation frameworks is ULO-based.默认坐标系统

A lower-left-origin coordinate system (LLO),Core Graphics framework is LLO-based

Before calling your view’sdrawRect:method, UIKit establishes the default coordinate system for drawing to the screen by making a graphics context available for drawing operations.

Obtaining Graphics Contexts

Most of the time, graphics contexts are configured for you. Each view object automatically creates a graphics context so that your code can start drawing immediately as soon as your customdrawRect:method is called. As part of this configuration, the underlyingUIViewclass creates a graphics context (aCGContextRefopaque type) for the current drawing environment.

大多数时候,图形上下文已经给你配置好了。每一个UIView对象会自动创建一个图形上下文对象,因此你可以在调用drawRect:后立即开始执行自己的自定义绘制。UIView隐式的为当前绘制环境创建了一个CGContextRef类型的绘制上下文对象。

If you want to draw somewhere other than your view (for example, to capture a series of drawing operations in a PDF or bitmap file), or if you need to call Core Graphics functions that require a context object, you must take additional steps to obtain a graphics context object. The sections below explain how.

如果需要绘制除了当前View以外其他的东西(例如,在位图或者PDF里面获取一系列的绘制操作),或者需要一个上下文对象来调用Core Graphics函数,那么你必须用其他的步骤去获取一个图形上下文对象。

Drawing to the Screen

如果使用Core Graphics函数在UIKit的view中绘制图形,你的绘制操作应该使用ULO坐标系统。

UIGraphicsGetCurrentContext可以获取当前绘制环境的CGContextRef对象。

如果你创建了一个PDF上下文,那么UIGraphicsGetCurrentContext会返回该PDF的CGContextRef对象。如果你要把它绘制到View,必须使用UIGraphicsGetCurrentContext返回的这个CGContextRef对象。

Drawing to Bitmap Contexts and PDF Contexts

Both the bitmap context and the PDF context provided by UIKit establish a ULO default coordinate system.The context that an app directly creates through Core Graphics, however, establishes a LLO default coordinate system.

bitmap上下文和PDF上下文是基于ULO坐标系统的。如果直接用Core Graphics的函数创建一个context,则是基于LLO坐标系统的。

Color and Color Spaces

UIColor对象提供了方便的方法指定颜色,不需要自己指定颜色空间,它已经被UIColor对象自动指定了。

也可以使用CGContextSetRGBStrokeColorandCGContextSetRGBFillColor创建和设置颜色,尽管Core Graphics支持使用其他的颜色空间创建颜色或者自定义颜色空间,但不推荐在自定义绘制代码中使用,自定义绘制应该一直使用RGB色彩空间。

Configuring the Graphics Context

上下文状态可以保存,使用CGContextSaveGState保存一个上下文状态,将状态推入堆中。接下来对上下文状态的操作不会影响保存到堆中的上下文状态。当需要恢复到之前的上下文状态时,可以使用CGContextRestoreGState恢复。这样在不同的上下文状态之间切换就不用重复执行配置代码。

Customizing the Coordinate Space

you can change the CTM by adding scaling, rotation, and translation factors to it and thereby change the size, orientation, and position of the default coordinate system relative to the underlying view or window.

Using Coordinate Transforms to Improve Drawing Performance

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • View Geometry and Coordinate Systems 二、视图几何和坐标系统 The defa...
    大灰很阅读 927评论 0 1
  • ViewsBecause view objects are the main way your applicati...
    梁光飞阅读 587评论 0 0
  • 堆和栈的区别: 一、堆栈空间分配区别: 1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的...
    miliPolo阅读 479评论 0 1
  • 跃上云天观大千,东南西北沧海间,纵横阡陌各有理,风雨云霞共长天。 原创作品 (Original Article)
    一诗一境界阅读 81评论 0 0
  • 在命运的长河里,总有自己不想面对的事;在人生的道路中,也会有许多坎坷的在阻止你,而在这其中是放弃还是前行 这也...
    杺杺jun阅读 232评论 2 1