【IOS笔记】View Programming Guide for iOS -1

原文:View Programming Guide for iOS

View and Window Architecture

Views and windows present your application’s user interface and handle the interactions with that interface. UIKit and other system frameworks provide a number of views that you can use as-is with little or no modification. You can also define custom views for places where you need to present content differently than the standard views allow.

Whether you use the system views or create your own custom views, you need to understand the infrastructure provided by the UIView and UIWindowclasses. These classes provide sophisticated facilities for managing the layout and presentation of views. Understanding how those facilities work is important for making sure your views behave appropriately when changes occur in your application.

 无论是使用系统提供的views还是创建你的自定义views,你都需要理解UIView和UIWindow提供的类架构。这些类提供了精致的设施来组织视图的布局和表现。如果理解了这些机制,在你修改代码的时候你就更能确信程序是运行正常的。

View Architecture Fundamentals

Most of the things you might want to do visually are done with view objects—instances of the UIView class. A view object defines a rectangular region on the screen and handles the drawing and touch events in that region. A view can also act as a parent for other views and coordinate the placement and sizing of those views. The UIView class does most of the work in managing these relationships between views, but you can also customize the default behavior as needed.

一个View对象定义了一个屏幕上的矩形,并负责矩形区域中的绘制和touch事件。一个view也可作为其他views的父视图,并负责协调子视图的位置和大小。

Views work in conjunction with Core Animation layers to handle the rendering and animating of a view’s content. Every view in UIKit is backed by a layer object (usually an instance of the CALayer class), which manages the backing store for the view and handles view-related animations. Most operations you perform should be through the UIView interface. However, in situations where you need more control over the rendering or animation behavior of your view, you can perform operations through its layer instead.

UIKit中的每个view都有一个layer 对象(通常是一个CALayer类的实例)

在需要更精细控制渲染和动画的场合,就需要操作view的layer对象。

To understand the relationship between views and layers, it helps to look at an example. Figure 1-1 shows the view architecture from the ViewTransitionssample application along with the relationship to the underlying Core Animation layers. The views in the application include a window (which is also a view), a generic UIView object that acts as a container view, an image view, a toolbar for displaying controls, and a bar button item (which is not a view itself but which manages a view internally). (The actual ViewTransitions sample application includes an additional image view that is used to implement transitions. For simplicity, and because that view is usually hidden, it is not included in Figure 1-1.) Every view has a corresponding layer object that can be accessed from that view’s layer property. (Because a bar button item is not a view, you cannot access its layer directly.) Behind those layer objects are Core Animation rendering objects and ultimately the hardware buffers used to manage the actual bits on the screen.

Figure 1-1  Architecture of the views in a sample application

【IOS笔记】View Programming Guide for iOS  -1

View Hierarchies and Subview Management

In addition to providing its own content, a view can act as a container for other views. When one view contains another, a parent-child relationship is created between the two views. The child view in the relationship is known as the subview and the parent view is known as the superview. The creation of this type of relationship has implications for both the visual appearance of your application and the application’s behavior.

除了提供自己的内容,一个view还可作为其他views的容器。childview-subview,parentview-superview。这种父子关系暗示了其它一些应用程序的外观和行为的特点。

Visually, the content of a subview obscures all or part of the content of its parent view. If the subview is totally opaque, then the area occupied by the subview completely obscures the corresponding area of the parent. If the subview is partially transparent, the content from the two views is blended together prior to being displayed on the screen. Each superview stores its subviews in an ordered array and the order in that array also affects the visibility of each subview. If two sibling subviews overlap each other, the one that was added last (or was moved to the end of the subview array) appears on top of the other.

子视图占据父视图部分或全部的位置。不透明子视图;半透明的;

父视图使用一个有序数组存储子视图,这对每个视图的可见性是有影响的。相互覆盖。

The superview-subview relationship also impacts several view behaviors. Changing the size of a parent view has a ripple effect that can cause the size and position of any subviews to change too. When you change the size of a parent view, you can control the resizing behavior of each subview by configuring the view appropriately. Other changes that affect subviews include hiding a superview, changing a superview’s alpha (transparency), or applying a mathematical transform to a superview’s coordinate system.

superview-subview 关系还影响视图的几个行为:父视图大小改变对子视图大小、位置影响的连锁反应。父视图的隐藏;改变父视图的alpha值,对父视图的坐标系应用数学变换;

The arrangement of views in a view hierarchy also determines how your application responds to events. When a touch occurs inside a specific view, the system sends an event object with the touch information directly to that view for handling. However, if the view does not handle a particular touch event, it can pass the event object along to its superview. If the superview does not handle the event, it passes the event object to its superview, and so on up the responder chain. Specific views can also pass the event object to an intervening responder object, such as a view controller. If no object handles the event, it eventually reaches the application object, which generally discards it.

视图层次的排列方式也会决定app对事件的响应。当一个view内部发生了touch事件,系统直接将包含touch信息的事件对象发送给那个view处理。如果这个view不处理,它可以将event对象传递给父视图。如果父视图不处理,可以继续向上传递,形成一个响应链。一个视图也可以传递事件对象给view controller这样的居中响应对象。如果没有对象处理这个事件,它最终会到达application对象,而application通常会丢弃它。

For more information about how to create view hierarchies, see Creating and Managing a View Hierarchy.

The View Drawing Cycle

The UIView class uses an on-demand drawing model for presenting content. When a view first appears on the screen, the system asks it to draw its content. The system captures a snapshot of this content and uses that snapshot as the view’s visual representation. If you never change the view’s content, the view’s drawing code may never be called again. The snapshot image is reused for most operations involving the view. If you do change the content, you notify the system that the view has changed. The view then repeats the process of drawing the view and capturing a snapshot of the new results.

UIView类使用按需绘制的模型。当一个视图第一次在屏幕上呈现,系统会要求视图绘制他的内容。系统会扑捉下视图的屏幕快照作为视图的可视化呈现。如果你没有改变视图的内容,系统就不会再调用视图的绘制代码。快照图像会多重用,如果你改变了视图的内容,你通知系统视图已经改变,系统会重新调用绘制代码,并且捕捉新的快照。

When the contents of your view change, you do not redraw those changes directly. Instead, you invalidate the view using either the setNeedsDisplay orsetNeedsDisplayInRect: method. These methods tell the system that the contents of the view changed and need to be redrawn at the next opportunity. The system waits until the end of the current run loop before initiating any drawing operations. This delay gives you a chance to invalidate multiple views, add or remove views from your hierarchy, hide views, resize views, and reposition views all at once. All of the changes you make are then reflected at the same time.

当视图内容改变时,你不需要直接重新绘制。你只需通过调用视图的 setNeedsDisplay orsetNeedsDisplayInRect方法使其失效即可。这些方法告诉系统视图已经改变,需要在下次重绘。系统在当前run loop结束前一直等到,直到发起任何绘图操作。这个延迟,给你有机会将多个视图失效、或从你的视图层次中添加或移除视图,隐藏视图,改变视图大小,改变视图位置 等等。所有这些改变会在同一个时间生效。

Note: Changing a view’s geometry does not automatically cause the system to redraw the view’s content. The view’s contentMode property determines how changes to the view’s geometry are interpreted. Most content modes stretch or reposition the existing snapshot within the view’s boundaries and do not create a new one. For more information about how content modes affect the drawing cycle of your view, see Content Modes.

注意:视图的几何变化不会自动引起系统重绘视图内容。视图的contentMode属性决定了改变视图形状后该如果展现。多数content mode拉伸或在视图边界内改变当前快照的位置,而不会重新创建一个快照。 

When the time comes to render your view’s content, the actual drawing process varies depending on the view and its configuration. System views typically implement private drawing methods to render their content. Those same system views often expose interfaces that you can use to configure the view’s actual appearance. For custom UIView subclasses, you typically override the drawRect: method of your view and use that method to draw your view’s content. There are also other ways to provide a view’s content, such as setting the contents of the underlying layer directly, but overriding the drawRect:method is the most common technique.

当重绘视图内容的时机来到时,实际的绘制过程由于views和其配置的不同而不同。系统视图通常实现私有的绘制方法来渲染它们的内容。系统视图通常会暴露可供你配置视图实际表现方式的接口。对于自定义UIView的子类,通常你需要override 子视图的drawRect方法。还有其他方式来提供视图的内容,例如直接修改下层的layer对象,但是override drawRect方法是最常用的技术。

For more information about how to draw content for custom views, see Implementing Your Drawing Code.

Content Modes

Each view has a content mode that controls how the view recycles its content in response to changes in the view’s geometry and whether it recycles its content at all. When a view is first displayed, it renders its content as usual and the results are captured in an underlying bitmap. After that, changes to the view’s geometry do not always cause the bitmap to be recreated. Instead, the value in the contentMode property determines whether the bitmap should be scaled to fit the new bounds or simply pinned to one corner or edge of the view.

每个视图都有一个content mode,控制view如何再利用其显示内容。当视图第一次显示的时候,它渲染其内容,最终结果会被捕捉到一个底层的位图中。然后,视图的几何变化不总会引起位图的重建。替代的,contentMode属性决定了是否这个位图应该被拉伸以适应新的边界,或者简单地靠到某个角,或者某个边。

The content mode of a view is applied whenever you do the following:

  • Change the width or height of the view’s frame or bounds rectangles.

  • Assign a transform that includes a scaling factor to the view’s transform property.

视图的内容模式应用于:

  • 改变视图frame或bounds的宽或高;
  • 给视图的transform属性赋值;

By default, the contentMode property for most views is set to UIViewContentModeScaleToFill, which causes the view’s contents to be scaled to fit the new frame size. Figure 1-2 shows the results that occur for some content modes that are available. As you can see from the figure, not all content modes result in the view’s bounds being filled entirely, and those that do might distort the view’s content.

大多数视图的contentMode缺省值是UIViewContentModeScaleToFill,这导致视图的内容会被拉伸以适应新的frame大小。图1-2展示了一些内容模式的表现。不是所有内容模式都会完全填满视图边界,而填满的会扭曲视图内容。

Figure 1-2  Content mode comparisons

【IOS笔记】View Programming Guide for iOS  -1

Content modes are good for recycling the contents of your view, but you can also set the content mode to the UIViewContentModeRedraw value when you specifically want your custom views to redraw themselves during scaling and resizing operations. Setting your view’s content mode to this value forces the system to call your view’s drawRect: method in response to geometry changes. In general, you should avoid using this value whenever possible, and you should certainly not use it with the standard system views.

 content mode对于视图内容的再利用有好处,不过在你希望在缩放或改变大小事也重绘视图时,你也可以将视图模式设置为UIViewContentModeRedraw。设置这个值,会强制系统在几何变化时每次都调用视图的drawRect方法。通常,你应该尽可能避免使用这个设置,对于标准系统视图则应该压根也不使用。

For more information about the available content modes, see UIView Class Reference.

Stretchable Views

You can designate a portion of a view as stretchable so that when the size of the view changes only the content in the stretchable portion is affected. You typically use stretchable areas for buttons or other views where part of the view defines a repeatable pattern. The stretchable area you specify can allow for stretching along one or both axes of the view. Of course, when stretching a view along two axes, the edges of the view must also define a repeatable pattern to avoid any distortion. Figure 1-3 shows how this distortion manifests itself in a view. The color from each of the view’s original pixels is replicated to fill the corresponding area in the larger view.

你可以指定视图的一部分作为可伸缩的,从而当视图大小改变时,仅仅只有可伸缩部分的内容受影响。典型使用可伸缩区域的例子,如按钮,定义了重复模式。你指定的可伸缩区域可允许沿着一个或两个坐标轴伸缩。当然,如果可沿两个轴缩放,则视图的边也必须定义可重复模式以避免变形。

Figure 1-3  Stretching the background of a button

【IOS笔记】View Programming Guide for iOS  -1

You specify the stretchable area of a view using the contentStretch property. This property accepts a rectangle whose values are normalized to the range 0.0 to 1.0. When stretching the view, the system multiplies these normalized values by the view’s current bounds and scale factor to determine which pixel or pixels need to be stretched. The use of normalized values alleviates the need for you to update the contentStretch property every time the bounds of your view change.

使用contentStretch属性定义可伸缩区域。

The view’s content mode also plays a role in determining how the view’s stretchable area is used. Stretchable areas are only used when the content mode would cause the view’s content to be scaled. This means that stretchable views are supported only with the UIViewContentModeScaleToFill,UIViewContentModeScaleAspectFit, and UIViewContentModeScaleAspectFill content modes. If you specify a content mode that pins the content to an edge or corner (and thus does not actually scale the content), the view ignores the stretchable area.

Note: The use of the contentStretch property is recommended over the creation of a stretchable UIImage object when specifying the background for a view. Stretchable views are handled entirely in the Core Animation layer, which typically offers better performance.

Built-In Animation Support

One of the benefits of having a layer object behind every view is that you can animate many view-related changes easily. Animations are a useful way to communicate information to the user and should always be considered during the design of your application. Many properties of the UIView class areanimatable—that is, semiautomatic support exists for animating from one value to another. To perform an animation for one of these animatable properties, all you have to do is:

  1. Tell UIKit that you want to perform an animation.

  2. Change the value of the property.

为每个view都提供一个layer对象的好处是为视图改变提供动画变得非常方便。在与用户交互信息方面动画非常重要,在设计app时需要始终考虑这个方面。UIView的许多属性都是支持动画的,也就是说,半自动的支持以动画形式从一个值变到另一个值。为使用动画属性,你需要:

1、告诉UIKit你希望之星一个动画;

2、改变属性值;

Among the properties you can animate on a UIView object are the following:

下面的属性是支持动画的:

  • frame—Use this to animate position and size changes for the view.

  • bounds—Use this to animate changes to the size of the view.

  • center—Use this to animate the position of the view.

  • transform—Use this to rotate or scale the view.

  • alpha—Use this to change the transparency of the view.

  • backgroundColor—Use this to change the background color of the view.

  • contentStretch—Use this to change how the view’s contents stretch.

One place where animations are very important is when transitioning from one set of views to another. Typically, you use a view controller to manage the animations associated with major changes between parts of your user interface. For example, for interfaces that involve navigating from higher-level to lower-level information, you typically use a navigation controller to manage the transitions between the views displaying each successive level of data. However, you can also create transitions between two sets of views using animations instead of a view controller. You might do so in places where the standard view-controller animations do not yield the results you want.

In addition to the animations you create using UIKit classes, you can also create animations using Core Animation layers. Dropping down to the layer level gives you much more control over the timing and properties of your animations.

For details about how to perform view-based animations, see Animations. For more information about creating animations using Core Animation, seeCore Animation Programming Guide and Core Animation Cookbook.

View Geometry and Coordinate Systems

The default coordinate system in UIKit has its origin in the top-left corner and has axes that extend down and to the right from the origin point. Coordinate values are represented using floating-point numbers, which allow for precise layout and positioning of content regardless of the underlying screen resolution. Figure 1-4 shows this coordinate system relative to the screen. In addition to the screen coordinate system, windows and views define their own local coordinate systems that allow you to specify coordinates relative to the view or window origin instead of relative to the screen.

UIKit的缺省坐标系原点在左上角,坐标轴向右和向下延伸。坐标值用浮点数表示,从而允许精确的布局和定位而不用考虑底层的屏幕分辨率。图1-4显示了屏幕坐标系。window和view也定义了它们自己的坐标系。

Figure 1-4  Coordinate system orientation in UIKit

【IOS笔记】View Programming Guide for iOS  -1

Because every view and window defines its own local coordinate system, you need to be aware of which coordinate system is in effect at any given time. Every time you draw into a view or change its geometry, you do so relative to some coordinate system. In the case of drawing, you specify coordinates relative to the view’s own coordinate system. In the case of geometry changes, you specify coordinates relative to the superview’s coordinate system. TheUIWindow and UIView classes both include methods to help you convert from one coordinate system to another.

由于每个view和window都定义了自己的坐标系,你需要在任何时候都关注哪个坐标系在生效。每一次你在view中绘图或者改变几何形状,都与某坐标系相关。在绘图时,你使用的是视图自己的坐标系。在做几何变换时,你使用父视图的坐标系。UIWindow和UIView类都包含了坐标系转换的方法。

Important: Some iOS technologies define default coordinate systems whose origin point and orientation differ from those used by UIKit. For example, Core Graphics and OpenGL ES use a coordinate system whose origin lies in the lower-left corner of the view or window and whose y-axis points upward relative to the screen. Your code must take such differences into account when drawing or creating content and adjust coordinate values (or the default orientation of the coordinate system) as needed.

注意:Core Graphics and OpenGL ES等IOS技术使用了不同于UIKit的坐标系。

The Relationship of the Frame, Bounds, and Center Properties

A view object tracks its size and location using its framebounds, and center properties:

view对象使用frame,bounds,center属性跟踪它的大小和位置:

  • The frame property contains the frame rectangle, which specifies the size and location of the view in its superview’s coordinate system.frame属性包含frame矩形,它使用父视图的坐标系指定了视图的大小和位置。

  • The bounds property contains the bounds rectangle, which specifies the size of the view (and its content origin) in the view’s own local coordinate system.bounds属性包含边界矩形,用视图自己的坐标系指定了视图的大小。

  • The center property contains the known center point of the view in the superview’s coordinate system.center属性保存了基于父视图坐标系的中心点坐标。

You use the center and frame properties primarily for manipulating the geometry of the current view. For example, you use these properties when building your view hierarchy or changing the position or size of a view at runtime. If you are changing only the position of the view (and not its size), thecenter property is the preferred way to do so. The value in the center property is always valid, even if scaling or rotation factors have been added to the view’s transform. The same is not true for the value in the frame property, which is considered invalid if the view’s transform is not equal to the identity transform.

使用center和frame属性主要用来操作视图的几何图形。例如,在运行时用来建立视图层次或改变位置和大小。如果你只改变视图的位置,使用center属性是最方便的途径。ceter属性值总是有效,甚至在你缩放和旋转视图的时候。而frame属性则不同。

You use the bounds property primarily during drawing. The bounds rectangle is expressed in the view’s own local coordinate system. The default origin of this rectangle is (0, 0) and its size matches the size of the frame rectangle. Anything you draw inside this rectangle is part of the view’s visible content. If you change the origin of the bounds rectangle, anything you draw inside the new rectangle becomes part of the view’s visible content.

bounds属性主要在绘图时使用。矩形的缺省原点是(0,0),它的大小与frame矩形相同。你在矩形范围内绘制的任何东西都是视图可见内容的一部分。如果你改变了bounds矩形的原点,在新矩形中的内容则变成了视图的可见部分。

Figure 1-5 shows the relationship between the frame and bounds rectangles for an image view. In the figure, the upper-left corner of the image view is located at the point (40, 40) in its superview’s coordinate system and the size of the rectangle is 240 by 380 points. For the bounds rectangle, the origin point is (0, 0) and the size of the rectangle is similarly 240 by 380 points.

Figure 1-5  Relationship between a view's frame and bounds【IOS笔记】View Programming Guide for iOS  -1

Although you can change the framebounds, and center properties independent of the others, changes to one property affect the others in the following ways:

尽管你可以单独改变frame,bounds,center属性,但是改变其中之一会以下列方式影响其它两个:

  • When you set the frame property, the size value in the bounds property changes to match the new size of the frame rectangle. The value in the centerproperty similarly changes to match the new center point of the frame rectangle.当你改变frame属性,会改变bounds的size。center也会跟着改变。

  • When you set the center property, the origin value in the frame changes accordingly.当改变center属性,会改变frame的原点。

  • When you set the size of the bounds property, the size value in the frame property changes to match the new size of the bounds rectangle.当改变bounds,会改变frame的size。

By default, a view’s frame is not clipped to its superview’s frame. Thus, any subviews that lie outside of their superview’s frame are rendered in their entirety. You can change this behavior, though, by setting the superview’s clipsToBounds property to YES. Regardless of whether or not subviews are clipped visually, touch events always respect the bounds rectangle of the target view’s superview. In other words, touch events occurring in a part of a view that lies outside of its superview’s bounds rectangle are not delivered to that view.

缺省地,一个视图的frame不裁剪于父视图的frame。因此,任何伸出父视图边界的子视图仍会渲染。你可以通过设置父视图的 clipsToBounds 属性为YES,来改变这个默认行为。

无论子视图在父视图显示时是否裁剪,touch事件始终会限制在父视图的范围内触发。

Coordinate System Transformations

Coordinate system transformations offer a way to alter your view (or its contents) quickly and easily. An affine transform is a mathematical matrix that specifies how points in one coordinate system map to points in a different coordinate system. You can apply affine transforms to your entire view to change the size, location, or orientation of the view relative to its superview. You can also use affine transforms in your drawing code to perform the same types of manipulations to individual pieces of rendered content. How you apply the affine transform therefore depends on context:

  • To modify your entire view, modify the affine transform in the transform property of your view.

  • To modify specific pieces of content in your view’s drawRect: method, modify the affine transform associated with the active graphics context.

坐标系统变换给予你快速方便改变视图的方法。仿射变换是一个数学矩阵,它定义了一个点如何从一个坐标系映射到另外一个。你可以对整个视图应用仿射变换以改变大小,位置或相对于父视图的方向。你也可以在你的绘图代码中使用仿射变换来为许多内容执行相同操作。如何应用仿射变换依赖于上下文:

  • 改变整个视图,修改transform属性;
  • 改变部分内容,在视图的drawRect方法中;

You typically modify the transform property of a view when you want to implement animations. For example, you could use this property to create an animation of your view rotating around its center point. You would not use this property to make permanent changes to your view, such as modifying its position or size a view within its superview’s coordinate space. For that type of change, you should modify the frame rectangle of your view instead.

通过改变transform属性可实现视图的动画效果。例如选中视图,通过仿射变换,可以不必修改基于父视图的位置和大小坐标。

Note: When modifying the transform property of your view, all transformations are performed relative to the center point of the view.

In your view’s drawRect: method, you use affine transforms to position and orient the items you plan to draw. Rather than fix the position of an object at some location in your view, it is simpler to create each object relative to a fixed point, typically (0, 0), and use a transform to position the object immediately prior to drawing. That way, if the position of the object changes in your view, all you have to do is modify the transform, which is much faster and less expensive than recreating the object at its new location. You can retrieve the affine transform associated with a graphics context using theCGContextGetCTM function and you can use the related Core Graphics functions to set or modify this transform during drawing.

在视图的drawRect方法中,使用仿射变换可确定需要绘制内容的位置和方向。相对于在你的视图中固定对象在某个位置,相对某个固定的来创建每个对象的方法会更简单,如(0,0),然后通过transform来使对象在正确的位置绘制。使用这种方式,如果对象位置发生改变,你需要做的仅仅是改变transform,这种方式快速而且简单。你可通过图形上下文的CGContextGetCTM得到仿射变换,并且在绘图过程中你可使用相关的Core Graphics 函数改变transform。

The current transformation matrix (CTM) is the affine transform in use at any given time. When manipulating the geometry of your entire view, the CTM is the affine transform stored in your view’s transform property. Inside your drawRect: method, the CTM is the affine transform associated with the active graphics context.

当前使用的transformation matrix (CTM) 是仿射变换。当操作整个视图的几何图形,CTM是存储在视图transform属性中的放射变换。

The coordinate system of each subview builds upon the coordinate systems of its ancestors. So when you modify a view’s transform property, that change affects the view and all of its subviews. However, these changes affect only the final rendering of the views on the screen. Because each view draws its content and lays out its subviews relative to its own bounds, it can ignore its superview’s transform during drawing and layout.

子视图的坐标系统建立在它们祖先的坐标系统之上。因此,当你改变一个视图的transform属性,会影响其所有子视图。然而,这些改变仅仅影响最终的屏幕绘制过程。因为每个视图绘制其内容,布局子视图是基于其自己的边界,它可以在绘制和布局时忽略其父视图的transform。

Figure 1-6 demonstrates how two different rotation factors combine visually when rendered. Inside the view’s drawRect: method, applying a 45 degree rotation factor to a shape causes that shape to appear rotated by 45 degrees. Applying a separate 45 degree rotation factor to the view then causes the shape to appear to be rotated by 90 degrees. The shape is still rotated by only 45 degrees relative to the view that drew it, but the view rotation makes it appear to be rotated by more.

如图1-6演示了两种不同的旋转参数是如果最终影响图形绘制的。

Figure 1-6  Rotating a view and its content【IOS笔记】View Programming Guide for iOS  -1

Important: If a view’s transform property is not the identity transform, the value of that view’s frame property is undefined and must be ignored. When applying transforms to a view, you must use the view’s bounds and center properties to get the size and position of the view. The frame rectangles of any subviews are still valid because they are relative to the view’s bounds.

注意:如果视图的transform属性不是 identity transform,视图的frame属性值是未定义的,并且需要忽略。当对一个视图应用transform,你必须使用视图的bounds和center属性来得到大小和位置。所有子视图的frame矩形仍然是合法值,因为它们是相对于视图的bounds。

For information about modifying your view’s transform property at runtime, see Translating, Scaling, and Rotating Views. For information about how to use transforms to position content during drawing, see Drawing and Printing Guide for iOS.

Points Versus Pixels

In iOS, all coordinate values and distances are specified using floating-point values in units referred to as points. The measurable size of a point varies from device to device and is largely irrelevant. The main thing to understand about points is that they provide a fixed frame of reference for drawing.

在IOS中,所有坐标值和距离用浮点数来度量,单位是point。不同设备的point尺寸大小差别很大。point的方式使得在不同设备上的frame值是固定的。

Table 1-1 lists the screen dimensions (measured in points) for different types of iOS-based devices in a portrait orientation. The width dimension is listed first, followed by the height dimension of the screen. As long as you design your interface to these screen sizes, your views will display correctly on the corresponding type of device.

Table 1-1  Screen dimensions for iOS-based devices

Device

Screen dimensions (in points)

iPhone and iPod touch devices with 4-inch Retina display

320 x 568

Other iPhone and iPod touch devices

320 x 480

iPad

768 x 1024

The point-based measuring system used for each type of device defines what is known as the user coordinate space. This is the standard coordinate space you use for nearly all of your code. For example, you use points and the user coordinate space when manipulating the geometry of a view or calling Core Graphics functions to draw the contents of your view. Although coordinates in the user coordinate space sometimes map directly to the pixels on the device’s screen, you should never assume that this is the case. Instead, you should always remember the following:

  • One point does not necessarily correspond to one pixel on the screen.

每个设备使用的,基于point的度量系统定义了用户坐标空间。这是标准坐标空间。

你需要始终记着:

  • 一个point不需要一定等于屏幕上的一个像素。

At the device level, all coordinates you specify in your view must be converted to pixels at some point. However, the mapping of points in the user coordinate space to pixels in the device coordinate space is normally handled by the system. Both UIKit and Core Graphics use a primarily vector-based drawing model where all coordinate values are specified using points. Thus, if you draw a curve using Core Graphics, you specify the curve using the same values, regardless of the resolution of the underlying screen.

在设备级别,所有你在视图中使用的坐标都要转换成像素。然而从基于point的用户坐标空间到基于像素的设备坐标空间的转换,是由系统来处理的。UIKit and Core Graphics使用的基于矢量的绘图模型都是使用的point坐标。因此,当你使用Core Graphics绘制图形,无论在什么屏幕分辨率下,你都为曲线指定相同的值。

When you need to work with images or other pixel-based technologies such as OpenGL ES, iOS provides help in managing those pixels. For static image files stored as resources in your application bundle, iOS defines conventions for specifying your images at different pixel densities and for loading the image that best matches the current screen resolution. Views also provide information about the current scale factor so that you can adjust any pixel-based drawing code manually to accommodate higher-resolution screens. The techniques for dealing with pixel-based content at different screen resolutions is described in Supporting High-Resolution Screens In Views in Drawing and Printing Guide for iOS.

当你需要使用图像等基于像素的技术,例如OpenGL ES,iOS为使用像素提供了帮助。对于在app bundle中存储的静态图像资源,iOS定义了指定像素密度的参数。视图还提供了缩放因子,从而你可以手工调整任何基于像素的代码来适配高分屏。

The Runtime Interaction Model for Views

Any time a user interacts with your user interface, or any time your own code programmatically changes something, a complex sequence of events takes place inside of UIKit to handle that interaction. At specific points during that sequence, UIKit calls out to your view classes and gives them a chance to respond on behalf of your application. Understanding these callout points is important to understanding where your views fit into the system. Figure 1-7shows the basic sequence of events that starts with the user touching the screen and ends with the graphics system updating the screen content in response. The same sequence of events would also occur for any programmatically initiated actions.

用户在与user interface交互的任何时候,或者任何通过编程方式修改的时候,在UIKit内部会为此交互产生一系列复杂的动作。理解下图中的标注,对于理解视图如何适应系统是很重要的。图1-7展示了从用户touch屏幕到最终更新屏幕显示所发生的一系列事件。对于通过编程方式出发的动作也是这个序列。

Figure 1-7  UIKit interactions with your view objects【IOS笔记】View Programming Guide for iOS  -1

The following steps break the event sequence in Figure 1-7 down even further and explain what happens at each stage and how you might want your application to react in response.

下面的步骤将图1-7中的序列分解的更加详细:

  1. The user touches the screen.用户touche屏幕

  2. The hardware reports the touch event to the UIKit framework.硬件向UIKit 报告touch事件。

  3. The UIKit framework packages the touch into a UIEvent object and dispatches it to the appropriate view. (For a detailed explanation of how UIKit delivers events to your views, see Event Handling Guide for iOS.)UIKit将touch打包到UIEvent对象,分发给相应view(详情参考 Event Handling Guide for iOS

  4. The event-handling code of your view responds to the event. For example, your code might:事件处理代码响应事件,你的代码会:

    • Change the properties (frame, bounds, alpha, and so on) of the view or its subviews.改变view及subview的frame、bounds,alpha等属性

    • Call the setNeedsLayout method to mark the view (or its subviews) as needing a layout update.调用setNeedsLayout方法标志此视图需要更新布局

    • Call the setNeedsDisplay or setNeedsDisplayInRect: method to mark the view (or its subviews) as needing to be redrawn.调用setNeedsDisplay或setNeedsDisplayInRect方法标记视图或其子视图需要重绘。

    • Notify a controller about changes to some piece of data.通知controller改变

    Of course, it is up to you to decide which of these things the view should do and which methods it should call.当然,视图应该如何做,调用哪个方法可由你决定。

  5. If the geometry of a view changed for any reason, UIKit updates its subviews according to the following rules:如果视图的几何形状不管什么原因改变了,UIKit根据以下规则更新其子视图:

    1. If you have configured autoresizing rules for your views, UIKit adjusts each view according to those rules. For more information about how autoresizing rules work, see Handling Layout Changes Automatically Using Autoresizing Rules.如果你给视图配置了自动适配大小的规则,UIKit根据这些规则调整每个视图。

    2. If the view implements the layoutSubviews method, UIKit calls it.如果视图实现了layoutSubviews方法,UIKit会调用它。

      You can override this method in your custom views and use it to adjust the position and size of any subviews. For example, a view that provides a large scrollable area would need to use several subviews as “tiles” rather than create one large view, which is not likely to fit in memory anyway. In its implementation of this method, the view would hide any subviews that are now offscreen or reposition them and use them to draw newly exposed content. As part of this process, the view’s layout code can also invalidate any views that need to be redrawn.你可以override这个方法来调整子视图的大小和位置。例如,一个具有很大滚动区域的视图会使用几个子视图而不是一个大视图,大视图太占用内存。在具体实现方法中,视图会隐藏不在屏幕上显示的部分,然后在需要显示的时候再重绘。

  6. If any part of any view was marked as needing to be redrawn, UIKit asks the view to redraw itself.任何视图的任何部分在需要重绘的时候,UIKit都要求它自己绘制自身。

    For custom views that explicitly define a drawRect: method, UIKit calls that method. Your implementation of this method should redraw the specified area of the view as quickly as possible and nothing else. Do not make additional layout changes at this point and do not make other changes to your application’s data model. The purpose of this method is to update the visual content of your view.对于自定义视图,需要显示定义drawRect方法,UIKit将调用此方法。你对此方法的实现需要尽可能快地重绘指定区域,并且不要做其它事。在此方法中,不要做其它的布局改变,也不要修改数据模型。此方法的目的就是更新视图显示。

    Standard system views typically do not implement a drawRect: method but instead manage their drawing at this time.标准系统视图一般不实现drawRect方法,但也会在这个时候完成绘制。

  7. Any updated views are composited with the rest of the application’s visible content and sent to the graphics hardware for display.任何更新后的视图与app的其余部分整合,然后被发送到图形硬件来显示。

  8. The graphics hardware transfers the rendered content to the screen.图形硬件传输渲染后的内容到屏幕。

Note: The preceding update model applies primarily to applications that use standard system views and drawing techniques. Applications that use OpenGL ES for drawing typically configure a single full-screen view and draw directly to the associated OpenGL ES graphics context. In such a case, the view may still handle touch events but, because it is full-screen, it would not need to lay out subviews. For more information about using OpenGL ES, see OpenGL ES Programming Guide for iOS.

In the preceding set of steps, the primary integration points for your own custom views are:

在前述的步骤中,自定义视图的主要集成点是:

These are the most commonly overridden methods for views but you may not need to override all of them. If you use gesture recognizers to handle events, you do not need to override any of the event-handling methods. Similarly, if your view does not contain subviews or its size does not change, there is no reason to override the layoutSubviews method. Finally, the drawRect: method is needed only when the contents of your view can change at runtime and you are using native technologies such as UIKit or Core Graphics to do your drawing.

这些是视图最常用的覆盖方法,但你不必覆盖所有这些方法。如果是使用手势识别,你不用覆盖任何事件处理方法。相似的,如果你的视图没有包含子视图,或者大小没有改变,也不需要覆盖layoutSubviews方法。最终,drawRect方法仅仅在你的视图内容在运行时会改变的时候,并且你要使用UIKit或Core Graphics这些原生技术来绘图。

It is also important to remember that these are the primary integration points but not the only ones. Several methods of the UIView class are designed to be override points for subclasses. You should look at the method descriptions in UIView Class Reference to see which methods might be appropriate for you to override in your custom implementations.

还有一点要明确,这些是主要集成点,但不是唯一的。UIView还设计了几个方法以方便在子类中覆盖。你可以参考UIView Class Reference 来找到合适的方法。

Tips for Using Views Effectively  高效使用视图的提示

Custom views are useful for situations where you need to draw something the standard system views do not provide, but it is your responsibility to ensure that the performance of your views is good enough. UIKit does everything it can to optimize view-related behaviors and help you achieve good performance in your custom views. However, you can help UIKit in this aspect by considering the following tips.

在系统视图不满足特定需要时,自定义视图是有用的,但是你需要保证高效的绘图。UIKit尽一切可能来优化视图相关行为以帮助你高效绘图。然而,你可以在以下方面帮助UIKit。

Important: Before optimizing your drawing code, you should always gather data about your view’s current performance. Measuring the current performance lets you confirm whether there actually is a problem and, if there is, gives you a baseline measurement against which you can compare future optimizations.

 重要:在优化你的绘图代码之前,你需要先收集测量数据

Views Do Not Always Have a Corresponding View Controller 视图不总是需要一个视图控制器

There is rarely a one-to-one relationship between individual views and view controllers in your application. The job of a view controller is to manage a view hierarchy, which often consists of more than one view used to implement some self-contained feature. For iPhone applications, each view hierarchy typically fills the entire screen, although for iPad applications a view hierarchy may fill only part of the screen.

As you design your application’s user interface, it is important to consider the role that view controllers will play. View controllers provide a lot of important behaviors, such as coordinating the presentation of views on the screen, coordinating the removal of those views from the screen, releasing memory in response to low-memory warnings, and rotating views in response to interface orientation changes. Circumventing these behaviors could cause your application to behave incorrectly or in unexpected ways.

For more information view controllers and their role in applications, see View Controller Programming Guide for iOS.

Minimize Custom Drawing 尽可能少的自定义绘制

Although custom drawing is necessary at times, it is also something you should avoid whenever possible. The only time you should truly do any custom drawing is when the existing system view classes do not provide the appearance or capabilities that you need. Any time your content can be assembled with a combination of existing views, your best bet is to combine those view objects into a custom view hierarchy.

Take Advantage of Content Modes  利用内容模式的优点

Content modes minimize the amount of time spent redrawing your views. By default, views use the UIViewContentModeScaleToFill content mode, which scales the view’s existing contents to fit the view’s frame rectangle. You can change this mode as needed to adjust your content differently, but you should avoid using the UIViewContentModeRedraw content mode if you can. Regardless of which content mode is in effect, you can always force your view to redraw its contents by calling setNeedsDisplay or setNeedsDisplayInRect:.

Declare Views as Opaque Whenever Possible 尽可能将视图定义为不透明的

UIKit uses the opaque property of each view to determine whether the view can optimize compositing operations. Setting the value of this property to YESfor a custom view tells UIKit that it does not need to render any content behind your view. Less rendering can lead to increased performance for your drawing code and is generally encouraged. Of course, if you set the opaque property to YES, your view must fill its bounds rectangle completely with fully opaque content.

将opaque置为YES可明确告诉UIKit不需要绘制底层的内容

Adjust Your View’s Drawing Behavior When Scrolling 通过滚动调整视图的绘制行为

Scrolling can incur numerous view updates in a short amount of time. If your view’s drawing code is not tuned appropriately, scrolling performance for your view could be sluggish. Rather than trying to ensure that your view’s content is pristine at all times, consider changing your view’s behavior when a scrolling operation begins. For example, you can reduce the quality of your rendered content temporarily or change the content mode while a scroll is in progress. When scrolling stops, you can then return your view to its previous state and update the contents as needed.

Do Not Customize Controls by Embedding Subviews 不要通过签入子视图来自定义控件

Although it is technically possible to add subviews to the standard system controls—objects that inherit from UIControl—you should never customize them in this way. Controls that support customizations do so through explicit and well-documented interfaces in the control class itself. For example, theUIButton class contains methods for setting the title and background images for the button. Using the defined customization points means that your code will always work correctly. Circumventing these methods, by embedding a custom image view or label inside the button, might cause your application to behave incorrectly now or at some point in the future if the button’s implementation changes.

上一篇:Quartz 2D Programming Guide


下一篇:iOS开发基础:最新的APP打包上架流程