子类化UIView的适当做法? [英] Proper practice for subclassing UIView?

查看:138
本文介绍了子类化UIView的适当做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一些基于UIView的自定义输入控件,我想确定设置视图的正确做法。当使用UIViewController时,使用 loadView 和相关 viewWill viewDid 方法,但是当子类化一个UIView时,最接近的methosds我有`awakeFromNib drawRect layoutSubviews 。 (我在设置和拆解回调方面的思考。)在我的例子中,我在 layoutSubviews 中设置框架和内部视图,但我没有看到任何屏幕上。



确保我的视图具有我想要的高度和宽度的最佳方法是什么?

解决方案

Apple在文档中清楚地定义了如何子类化 UIView



特别是看看 initWithFrame: layoutSubviews 。前者用于设置 UIView 的框架,而后者用于设置框架和其子视图的布局。



还要记住,只有当你以程序方式实例化你的 UIView 时,才会调用 initWithFrame:如果从nib文件(或故事板)加载它,将使用 initWithCoder:。在 initWithCoder:中,框架尚未计算,因此您无法修改在Interface Builder中设置的框架。如在此答案中中所述,您可能会认为调用 initWithFrame:从 initWithCoder:中设置框架。



最后,如果你从一个nib(或一个故事板)加载你的 UIView ,你也有 awakeFromNib 执行自定义框架和布局初始化,因为当 awakeFromNib 被调用时,保证层次结构中的每个视图都已被解除归档和初始化。



<$ c的文档$ c> NSNibAwaking


向其他对象发送的消息可以从awakeFromNib-by (当然不是一定被唤醒)


这也值得注意的是, autolayout你不应该显式地设置视图的框架。



直接从 /developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html\">文档


覆盖方法



初始化




  • strong> initWithFrame: 建议您实现此方法。


  • initWithCoder : 如果从Interface Builder nib文件加载视图并且您的视图需要自定义
    初始化,请实现此方法。


  • layerClass 仅当您希望视图对其后备存储使用不同的Core Animation图层时,才实现此方法。例如,
    如果你使用OpenGL ES来做你的绘图,你想要
    重写这个方法并返回CAEAGLLayer类。




绘图和列印




  • drawRect : 如果您的视图绘制自定义内容,请实施此方法。如果您的视图没有做任何自定义绘图,请避免覆盖此
    方法。


  • drawRect:forViewPrintFormatter: 只有在您想在打印期间以不同的方式绘制视图内容时才实施此方法。



$ b b

约束




  • requiresConstraintBasedLayout


  • updateConstraints 如果您的视图类需要约束才能正常工作, 如果您的视图需要在子视图之间创建自定义约束,请实施此方法。


  • alignmentRectForFrame: code> frameForAlignmentRect: 实施这些方法以覆盖视图与其他视图的对齐方式。




版面




  • strong> sizeThatFits: 如果您希望视图具有不同于调整
    操作时的默认大小,请实施此方法。例如,您可以使用此方法防止
    视图缩小到无法正确显示子视图
    的点。


  • layoutSubviews 如果您需要更精确地控制子视图的布局,而不是约束或
    自动调整行为提供的话,那么实现此方法。 / p>


  • didAddSubview: willRemoveSubview


  • <$ c>

    $ c> willMoveToSuperview:
    didMoveToSuperview 根据需要实施这些方法来跟踪当前视图
    层次结构。


  • willMoveToWindow: didMoveToWindow 根据需要实施这些方法来跟踪视图到不同窗口的移动。




事件处理:




  • touchesBegan:withEvent: touchesMoved:withEvent: touchesEnded:withEvent: touchesCancelled:withEvent:如果需要处理触摸事件,直。 (对于
    基于手势的输入,请使用手势识别器。)


  • gestureRecognizerShouldBegin: 如果您的视图直接处理触摸事件,并希望防止附加的
    手势识别器触发其他操作,请实施此方法。




I'm working on some custom UIView-based input controls, and I'm trying to ascertain proper practice for setting up the view. When working with a UIViewController, it's fairly simple to use the loadView and related viewWill, viewDid methods, but when subclassing a UIView, the closest methosds I have are `awakeFromNib, drawRect, and layoutSubviews. (I'm thinking in terms of setup and teardown callbacks.) In my case, I'm setting up my frame and internal views in layoutSubviews, but I'm not seeing anything onscreen.

What is the best way to ensure that my view has the correct height and width that I want it to have? (My question applies regardless of if I'm using autolayout, although there might be two answers.) What's the proper "best practice"?

解决方案

Apple defined pretty clearly how to subclass UIView in the doc.

Check out the list below, especially take a look at initWithFrame: and layoutSubviews. The former is intended to setup the frame of your UIView whereas the latter is intended to setup the frame and the layout of its subviews.

Also remember that initWithFrame: is called only if you are instantiating your UIView programmatically. If you are loading it from a nib file (or a storyboard), initWithCoder: will be used. And in initWithCoder: the frame hasn't been calculated yet, so you cannot modify the frame you set up in Interface Builder. As suggested in this answer you may think of calling initWithFrame: from initWithCoder: in order to setup the frame.

Finally, if you load your UIView from a nib (or a storyboard), you also have the awakeFromNib opportunity to perform custom frame and layout initializations, since when awakeFromNib is called it's guaranteed that every view in the hierarchy has been unarchived and initialized.

From the doc of NSNibAwaking

Messages to other objects can be sent safely from within awakeFromNib—by which time it’s assured that all the objects are unarchived and initialized (though not necessarily awakened, of course)

It's also worth noting that with autolayout you shouldn't explicitly set the frame of your view. Instead you are supposed to specify a set of sufficient constraints, so that the frame is automatically calculated by the layout engine.

Straight from the documentation:

Methods to Override

Initialization

  • initWithFrame: It is recommended that you implement this method. You can also implement custom initialization methods in addition to, or instead of, this method.

  • initWithCoder: Implement this method if you load your view from an Interface Builder nib file and your view requires custom initialization.

  • layerClass Implement this method only if you want your view to use a different Core Animation layer for its backing store. For example, if you are using OpenGL ES to do your drawing, you would want to override this method and return the CAEAGLLayer class.

Drawing and printing

  • drawRect: Implement this method if your view draws custom content. If your view does not do any custom drawing, avoid overriding this method.

  • drawRect:forViewPrintFormatter: Implement this method only if you want to draw your view’s content differently during printing.

Constraints

  • requiresConstraintBasedLayout Implement this class method if your view class requires constraints to work properly.

  • updateConstraints Implement this method if your view needs to create custom constraints between your subviews.

  • alignmentRectForFrame:, frameForAlignmentRect: Implement these methods to override how your views are aligned to other views.

Layout

  • sizeThatFits: Implement this method if you want your view to have a different default size than it normally would during resizing operations. For example, you might use this method to prevent your view from shrinking to the point where subviews cannot be displayed correctly.

  • layoutSubviews Implement this method if you need more precise control over the layout of your subviews than either the constraint or autoresizing behaviors provide.

  • didAddSubview:, willRemoveSubview: Implement these methods as needed to track the additions and removals of subviews.

  • willMoveToSuperview:, didMoveToSuperview Implement these methods as needed to track the movement of the current view in your view hierarchy.

  • willMoveToWindow:, didMoveToWindow Implement these methods as needed to track the movement of your view to a different window.

Event Handling:

  • touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, touchesCancelled:withEvent: Implement these methods if you need to handle touch events directly. (For gesture-based input, use gesture recognizers.)

  • gestureRecognizerShouldBegin: Implement this method if your view handles touch events directly and might want to prevent attached gesture recognizers from triggering additional actions.

这篇关于子类化UIView的适当做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆