UIKit学习笔记—第三节Views

各位iOS开发大佬们好:
我是一名Swift+SwiftUI栈的iOS小白,目前还在上大三,最近准备实习,面试的过程中发现现在大公司很多还在用OC + UIKit的技术栈,OC我还在考虑要不要学,目前想先把UIKit学完,这是我在官网学习UIKit英文文档时摘录的本人认为的重点,如果你们也觉得对你们有用的话欢迎持续关注,我大概一天更一节,有事除外。格式什么的我也就不做了,翻译都是我自己翻译的,哪里不对欢迎在评论区指正,感谢各位大佬支持

今天2021年11月29日
这一章叫做Views

View的职责和功能有很多,比如布局、管理子视图,绘图和动画,处理事件
还是一样,我本人不喜欢IB做界面,所以只看了编程界面的部分

After you create a view, you must add it to a window (or to another view in a window) before it can become visible.
创建View之后必须添加到Window或已在Window中的View上使之可视
|

The UIView class contains a tag property that you can use to tag individual view objects with an integer value
You can use tags to uniquely identify views inside your view hierarchy and to perform searches for those views at runtime. (Tag-based searches are faster than iterating the view hierarchy yourself.) The default value for the tag property is 0.
To search for a tagged view, use the viewWithTag: method of UIView. This method performs a depth-first search of the receiver and its subviews. It does not search superviews or other parts of the view hierarchy.
UIView类包含一个可以使用整数标记个别视图对象的tag 属性
你可以使用tags唯一标识视图层级中的view并且在运行时查找这些视图。(基于tag的查找效率高于普通的迭代视图层级)tag属性的默认值为0
使用UIView的viewWithTag:方法查找被标记的View,查找方式为深度优先遍历,只会DFS子视图,不会回溯父视图

If you prefer to create your views programmatically instead, you create and initialize them and then use the following methods to arrange them into hierarchies:
To add a subview to a parent, call the addSubview: method of the parent view. This method adds the subview to the end of the parent’s list of subviews.
To insert a subview in the middle of the parent’s list of subviews, call any of the insertSubview:… methods of the parent view. Inserting a subview in the middle of the list visually places that view behind any views that come later in the list.
To reorder existing subviews inside their parent, call the bringSubviewToFront:, sendSubviewToBack:, or exchangeSubviewAtIndex:withSubviewAtIndex: methods of the parent view. Using these methods is faster than removing the subviews and reinserting them.
To remove a subview from its parent, call the removeFromSuperview method of the subview (not the parent view).
When adding a subview to its parent, the subview’s current frame rectangle denotes its initial position inside the parent view. A subview whose frame lies outside of its superview’s visible bounds is not clipped by default. If you want your subview to be clipped to the superview’s bounds, you must explicitly set the clipsToBounds property of the superview to YES.
One place where you might add subviews to a view hierarchy is in the loadView or viewDidLoad methods of a view controller. If you are building your views programmatically, you put your view creation code in the loadView method of your view controller. Whether you create your views programmatically or load them from a nib file, you could include additional view configuration code in the viewDidLoad method.

将视图加入视图层级中的步骤:
调用视图的addSubview: 方法,此方法将子视图压入视图的子视图栈的栈顶
可以调用insertSubview:…将子视图插入视图层级的任意层
调用 bringSubviewToFront:, sendSubviewToBack:,或 exchangeSubviewAtIndex:withSubviewAtIndex: 方法调整视图层级
调用removeFromSuperview 从父视图中移除子视图
如果子视图的显示范围超出了父视图的显示范围,默认不会裁剪子视图的内容,可以设置clipsToBounds 属性为YES来裁剪子视图,

Superviews automatically retain their subviews, so after embedding a subview it is safe to release that subview. In fact, doing so is recommended because it prevents your application from retaining the view one time too many and causing a memory leak later. Just remember that if you remove a subview from its superview and intend to reuse it, you must retain the subview again. The removeFromSuperview method autoreleases a subview before removing it from its superview. If you do not retain the view before the next event loop cycle, the view will be released.

父视图自动保存他们的子视图,所以在添加子视图之后释放子视图是安全的,避免产生内存泄漏 removeFromSuperview 方法会在视图被从父视图上移除前自动释放,如果没有在下一个事件周期前保存它,那么他会被释放

When you add a subview to another view, UIKit notifies both the parent and child views of the change. If you implement custom views, you can intercept these notifications by overriding one or more of the willMoveToSuperview:, willMoveToWindow:, willRemoveSubview:, didAddSubview:, didMoveToSuperview, or didMoveToWindow methods. You can use these notifications to update any state information related to your view hierarchy or to perform additional tasks.
当添加子视图时,UIKit会通知所有和他有关系的视图,如果你实现了自定义视图,你可以通过重写willMoveToSuperview:, willMoveToWindow:, willRemoveSubview:, didAddSubview:, didMoveToSuperview, 或 didMoveToWindow方法来完成通知或执行额外的操作

After creating a view hierarchy, you can navigate it programmatically using the superview and subviews properties of your views. The window property of each view contains the window in which that view is currently displayed (if any). Because the root view in a view hierarchy has no parent, its superview property is set to nil. For views that are currently onscreen, the window object is the root view of the view hierarchy.
创建视图层级之后可以通过编程superview 和 subviews属性浏览它们,根视图的父视图为nil,根视图为Window对象

To hide a view visually, you can either set its hidden property to YES or change its alpha property to 0.0. A hidden view does not receive touch events from the system. However, hidden views do participate in autoresizing and other layout operations associated with the view hierarchy.
Important: If you hide a view that is currently the first responder, the view does not automatically resign its first responder status. Events targeted at the first responder are still delivered to the hidden view. To prevent this from happening, you should force your view to resign the first responder status when you hide it.
If you want to animate a view’s transition from visible to hidden (or the reverse), you must do so using the view’s alpha property. The hidden property is not an animatable property, so any changes you make to it take effect immediately.
通过设置hidden和alpha属性来隐藏视图,被隐藏的视图将不会接收点击事件(注意区分响应事件),但它会配合视图层级进行自动布局调整。
被隐藏的视图不会自动屏蔽响应事件,你需要自己去强制避免
Alpha是可动画属性,hidden不可动画,因为没有值的连续性改变

There are two ways to locate views in a view hierarchy:
Store pointers to any relevant views in an appropriate location, such as in the view controller that owns the views.
Assign a unique integer to each view’s tag property and use the viewWithTag: method to locate it
两个方式在视图层级中定位视图
将指向任何相关视图的指针存储在适当的位置,例如拥有视图的视图控制器中。
为每个View的tag 属性分配唯一整数,并且使用viewWithTag: 方法定位

If you wanted to save the list of views that are currently visible in your application, you would write out the tags of each visible view to a file.This is simpler than archiving the actual view objects, especially in situations where you are tracking only which views are currently visible. When your application is subsequently loaded, you would then re-create your views and use the saved list of tags to set the visibility of each view, and thereby return your view hierarchy to its previous state.
在一些情况下tag方法比指针方法更有效:如果您想保存应用程序中当前可见的视图列表,您将把每个可见视图的标签写到文件中。这比归档实际视图对象更简单,特别是在您仅跟踪当前可见的视图的情况下。当您的应用程序随后加载时,您将重新创建视图,并使用保存的标签列表设置每个视图的可见性,从而将视图层次结构恢复到之前的状态。

Translating, Scaling, and Rotating Views
Every view has an associated affine transform that you can use to translate, scale, or rotate the view’s content. View transforms alter the final rendered appearance of the view and are often used to implement scrolling, animations, or other visual effects.
每个视图都可以通过仿射变换去缩放,旋转视图内容
视图转换改变了视图的最终渲染外观,通常用于实现滚动、动画或其他视觉效果。
Even if the amounts of rotation and translation are the same in each case, the sequence of the transformations affects the final results.
转换的添加顺序影响转换最终效果

转换坐标系统可以调用的方法
UIView中
convertPoint:fromView:
convertRect:fromView:
convertPoint:toView:
convertRect:toView:
UIWindow中
convertPoint:fromWindow:
convertRect:fromWindow:
convertPoint:toWindow:
convertRect:toWindow:

Whenever the size of a view changes, the size and position of its subviews must change accordingly.
子视图必须随着父视图的变化而变化,可以通过自动或手动方式来调整,通过设置规则来自动布局,也可根据需要手动布局。

Layout changes can occur whenever any of the following events happens in a view:
The size of a view’s bounds rectangle changes.
An interface orientation change occurs, which usually triggers a change in the root view’s bounds rectangle.
The set of Core Animation sublayers associated with the view’s layer changes and requires layout.
Your application forces layout to occur by calling the setNeedsLayout or layoutIfNeeded method of a view.
Your application forces layout by calling the setNeedsLayout method of the view’s underlying layer object.
当视图中出现以下任一事件是都可能会导致布局更改
View的尺寸改变
视图方向改变
跟View的layer有关的sublayer发生变化
通过调用View或View的layer的 setNeedsLayout 或 layoutIfNeeded 方法强制使布局发生变化

When you change the size of a view, the position and size of any embedded subviews usually needs to change to account for the new size of their parent. The autoresizesSubviews property of the superview determines whether the subviews resize at all. If this property is set to YES, the view uses the autoresizingMask property of each subview to determine how to size and position that subview. Size changes to any subviews trigger similar layout adjustments for their embedded subviews.
autoresizesSubviews属性决定了是否自动根据父视图更改尺寸和布局,如果为是,视图根据每个子视图的autoresizingMask属性决定具体实现方式
在这里插入图片描述

在这里插入图片描述

If a view’s transform property does not contain the identity transform, the frame of that view is undefined and so are the results of its autoresizing behaviors.
如果视图的transform 属性不包含身份转换,那么视图的frame和自动布局的结果未知
After the automatic autoresizing rules for all affected views have been applied, UIKit goes back and gives each view a chance to make any necessary manual adjustments to its superview
Whenever the size of a view changes, UIKit applies the autoresizing behaviors of that view’s subviews and then calls the layoutSubviews method of the view to let it make manual changes. You can implement the layoutSubviews method in custom views when the autoresizing behaviors by themselves do not yield the results you want. Your implementation of this method can do any of the following:
自动调整大小之后,UIKit还会给每个子视图一个做自定义调整的机会,你可以在layoutSubviews 方法中实现以下改变
改变大小和位置
增删View或layer
通过调用setNeedsDisplay 或 setNeedsDisplayInRect: 方法强制重绘子视图

When a scroll event happens, the root view calls its setNeedsLayout method to initiate a layout change. Its layoutSubviews method then repositions the tile views based on the amount of scrolling that occurred. As tiles scroll out of the view’s visible area, the layoutSubviews method moves the tiles to the incoming edge, replacing their contents in the process.
应用最多的其实就是ScrollView,当滚动事件发生时,根视图调用setNeedsLayout方法初始化一个布局更改,之后layoutSubviews方法根据滚动的程度重新定位其子视图

When writing your layout code, be sure to test your code in the following ways:
Change the orientation of your views to make sure the layout looks correct in all supported interface orientations.
Make sure your code responds appropriately to changes in the height of the status bar. When a phone call is active, the status bar height increases in size, and when the user ends the call, the status bar decreases in size.
当编写布局代码时,确保代码可以通过如下测试
确保布局在任何方向都看着舒服
确保代码可以对状态栏的高度改变做出正确回应

运行时修改视图
In a view controller:
A view controller has to create its views before showing them. It can load the views from a nib file or create them programmatically. When those views are no longer needed, it disposes of them.
When a device changes orientations, a view controller might adjust the size and position of views to match. As part of its adjustment to the new orientation, it might hide some views and show others.
When a view controller manages editable content, it might adjust its view hierarchy when moving to and from edit mode. For example, it might add extra buttons and other controls to facilitate editing various aspects of its content. This might also require the resizing of any existing views to accommodate the extra controls.
In animation blocks:
When you want to transition between different sets of views in your user interface, you hide some views and show others from inside an animation block.
When implementing special effects, you might use an animation block to modify various properties of the view. For example, to animate changes to the size of a view, you would change the size of its frame rectangle.
Other ways:
When touch events or gestures occur, your interface might respond by loading a new set of views or changing the current set of views. For information about handling events, see Event Handling Guide for iOS.
When the user interacts with a scroll view, a large scrollable area might hide and show tile subviews. For more information about supporting scrollable content, see Scroll View Programming Guide for iOS.
When the keyboard appears, you might reposition or resize views so that they do not lie underneath the keyboard. For information about how to interact with the keyboard, see Text Programming Guide for iOS.
View controllers are a common place to initiate changes to your views. Because a view controller manages the view hierarchy associated with the content being displayed, it is ultimately responsible for everything that happens to those views. When loading its views or handling orientation changes, the view controller can add new views, hide or replace existing ones, and make any number of changes to make the views ready for the display. And if you implement support for editing your view’s content, the setEditing:animated: method in UIViewController gives you a place to transition your views to and from their editable versions.
Animation blocks are another common place to initiate view-related changes. The animation support built into the UIView class makes it easy to animate changes to view properties. You can also use the transitionWithView:duration:options:animations:completion: or transitionFromView:toView:duration:options:completion: methods to swap out entire sets of views for new ones.

没啥可翻的,就是可以在VC,动画闭包或其他地方比如键盘啊什么的在运行时修改视图,动画闭包中可以通过transitionWithView:duration:options:animations:completion: 或 transitionFromView:toView:duration:options:completion: 这两个方法实现整个视图的换入换出
The type of layer associated with a view cannot be changed after the view is created. Therefore, each view uses the layerClass class method to specify the class of its layer object. The default implementation of this method returns the CALayer class and the only way to change this value is to subclass, override the method, and return a different value. You can change this value to use a different kind of layer.
一般情况下视图被创建之后它的layer类型就不能更改了,每个view都可通过layerClass类方法指定自己layer的类型,默认为CALayer,但也可通过继承,重写此方法去返回一个其他类型的layer
In addition, the view always assigns itself as the delegate of its layer object. At this point, the view owns its layer and the relationship between the view and layer must not change. You must also not assign the same view as the delegate of any other layer object. Changing the ownership or delegate relationships of the view will cause drawing problems and potential crashes in your application.
View将自己视为它layer对象的委托,一旦创建,这种关系将不能改变,禁止给其他layer对象委托相同的视图,会造成app崩溃

Define the appropriate initialization methods for your view: For
views you plan to create programmatically, override the
initWithFrame: method or define a custom initialization method. For
views you plan to load from nib files, override the initWithCoder:
method. Use this method to initialize your view and put it into a
known state. Implement a dealloc method to handle the cleanup of
any custom data. To handle any custom drawing, override the
drawRect: method and do your drawing there. Set the
autoresizingMask property of the view to define its autoresizing
behavior. If your view class manages one or more integral subviews,
do the following: Create those subviews during your view’s
initialization sequence. Set the autoresizingMask property of each
subview at creation time. If your subviews require custom layout,
override the layoutSubviews method and implement your layout code
there. To handle touch-based events, do the following: Attach any
suitable gesture recognizers to the view by using the
addGestureRecognizer: method. For situations where you want to
process the touches yourself, override the touchesBegan:withEvent:,
touchesMoved:withEvent:, touchesEnded:withEvent:, and
touchesCancelled:withEvent: methods. (Remember that you should
always override the touchesCancelled:withEvent: method,
regardless of which other touch-related methods you override.)
If you want the printed version of your view to look different
from the onscreen version, implement the
drawRect:forViewPrintFormatter: method. For detailed information
about how to support printing in your views, see Drawing and
Printing Guide for iOS. In addition to overriding methods,
remember that there is a lot you can do with the view’s existing
properties and methods. For example, the contentMode and
contentStretch properties let you change the final rendered
appearance of your view and might be preferable to redrawing the
content yourself. In addition to the UIView class itself, there are
many aspects of a view’s underlying CALayer object that you can
configure directly or indirectly. You can even change the class of
the layer object itself.

上述条目列出了在自定义视图时可以重写的方法和一些你可以提供的行为
重写初始化器
实现dealloc方法
重写drawRect方法
设置autoresizingMask属性定义自动布局的行为
如果视图管理着子视图,那么:
初始化时创建子视图
为每个子视图设置autosizingMask属性,重写layoutSubviews方法来实现额外布局操作
addGestureRecognizer: 方法可识别各种手势
重写touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, 和 touchesCancelled:withEvent: 方法如果你想传递触摸事件(必须重写touchesCancelled:withEvent:方法
For views that need to do custom drawing, you need to override the drawRect: method and do your drawing there
if your drawRect: method might be called frequently, you should do everything you can to optimize your drawing code and draw as little as possible each time the method is called.
The current graphics context is valid only for the duration of one call to your view’s drawRect: method. UIKit might create a different graphics context for each subsequent call to this method, so you should not try to cache the object and use it later.
重写drawRect: 方法实现绘制视图内容,如果可能被多次调用,那么应使它最优,即执行最少任务,每次drawRect: 期间,UIKit会为其配置基础上下文环境,但每次调用所配置的上下文环境都不同,因此不应该尝试缓存对象并在稍后使用它。
如果能保证视图永远不透明,那么一定要设置opaque属性为YES,避免不必要的绘制,提高性能,
clearsContextBeforeDrawing 属性为NO时将会在视图滚动时将即将绘制的内容用不透明的黑色表示,如果为YES则会正常填充内容
If you plan to track multi-finger gestures from your view’s event-handler methods, you need to enable multitouch events by setting the multipleTouchEnabled property of your view to YES
默认不支持多指触控,通过
设置multipleTouchEnabled 属性为YES即可

To prevent events from reaching any of your views, you can also use the beginIgnoringInteractionEvents and endIgnoringInteractionEvents methods of the UIApplication object.
The animation methods of UIView typically disable touch events while animations are in progress. You can override this behavior by configuring the animation appropriately.
通过使用UIApplication对象的beginIgnoringInteractionEvents 和 endIgnoringInteractionEvents 方法使整个app无法触控,这将会影响整个app,而非只是某个视图
通过 userInteractionEnabled 属性使视图无法响应事件,
动画进行中无法响应其他事件,你可以适当配置

As it handles touch events, UIKit uses the hitTest:withEvent: and pointInside:withEvent: methods of UIView to determine whether a touch event occurred inside a given view’s bounds. Although you rarely need to override these methods, you could do so to implement custom touch behaviors for your view.
UIKit使用hitTest:withEvent: 和 pointInside:withEvent: 方法决定事件是否在给定的View中发生,你可以通过重写实现自定义行为

If your view class allocates any memory, stores references to any custom objects, or holds resources that must be released when the view is released, you must implement a dealloc method. The system calls the dealloc method when your view’s retain count reaches zero and it is time to deallocate the view. Your implementation of this method should release any objects or resources held by the view and then call the inherited implementation,

实现dealloc方法以便于ARC回收,必须在实现中释放所有View持有的资源和对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值