如何在子类化视图时减少代码冗余?

Posted

技术标签:

【中文标题】如何在子类化视图时减少代码冗余?【英文标题】:How to reduce code redundancy while subclassing views? 【发布时间】:2015-01-24 17:44:41 【问题描述】:

我有一个需求,我需要更改 UIComponent,如 UIButton、UIView 和 UITextField。我需要做的只是将边框的半径更改为圆形而不是默认的锐角矩形。

我这样做的方法是将 UIView 子类化为 UIViewRoundCornerUIButton 子类化为 UIButtonRoundCornerUITextField 子类化为 UITextFieldRoundCorner,并且在我拥有的每个子类中用这个覆盖了drawRect方法:

- (void)drawRect:(CGRect)rect 
    // Drawing code
    CALayer *layer = [self layer];
    [layer setMasksToBounds:YES];
    [layer setCornerRadius:3.0f];
    [layer setBorderWidth:1.0f];

代码是多余的,我正试图弄清楚如何删除这种冗余。由于所有这些元素都是从 UIView 继承的,是否有可能以某种方式继承 UIView 并在所有其他视图中实现?

【问题讨论】:

仅供参考 - 使用 drawRect: 调整图层不是正确的做法。 drawRect: 可以在控件的生命周期内多次调用,但您只需调整层一次。以适当的init... 方法执行此操作。 感谢您的建议 :)。我会马上实施。 【参考方案1】:

您根本不需要子类化来执行此操作。 Objective-C 有一个很棒的特性,它允许您向现有 类添加行为:categories。

您可以在UIView 上的类别中添加方法(我们称之为RoundedCorners):

@implementation UIView (RoundedCorners)

- (void)ps_addRoundedCorners;

@end

@implementation UIView (RoundedCorners)

- (void)ps_addRoundedCorners 
    CALayer *layer = [self layer];
    [layer setMasksToBounds:YES];
    [layer setCornerRadius:3.0f];
    [layer setBorderWidth:1.0f]; 


@end

并将其与任何UIView 子类一起使用:

UIButton *button = ...  //create a button somehow
[button ps_addRoundedCorners];

方法名称中的ps_ 前缀用于避免名称冲突(以防其他人在私有框架中添加同名方法)。

【讨论】:

【参考方案2】:
protocol RoundedCorner 
    func makeCornerRadius(radius:CGFloat)


extension RoundedCorner where Self:UIView
    func makeCornerRadius(radius:CGFloat)
        self.layer.cornerRadius = radius
    


class CustomButton: UIButton, RoundedCorner 

    override func drawRect(rect: CGRect) 
        super.drawRect(rect)
        self.makeCornerRadius(5)
    

您可以创建一个协议并将该协议扩展为默认实现。然后对于您想要角半径的每个自定义视图,只需实现该协议。这样可以最大限度地减少代码冗余。

【讨论】:

为什么不扩展 UIview 本身而不是扩展协议??

以上是关于如何在子类化视图时减少代码冗余?的主要内容,如果未能解决你的问题,请参考以下文章

点击时如何对子类 UIView 执行操作?

继承与派生

如何正确子类化从 Swift 中的 xib 加载的视图类?

如何在许多子类中使用 UITableViewDelegate 子类化 UIViewController

如何子类化 UITableView?

如何利用子视图(非分部页面)