使用常见的UIView子类UILabel和UITextView

时间:2014-06-27 18:20:40

标签: objective-c uiview uilabel uitextview subclass

我正在尝试添加渐变作为UILabel和UITextView的背景。我通过覆盖每个子类中的drawRect方法并为每个子类添加相同的属性来绘制渐变。我的问题是如何最好地简化/组合这些代码,因为drawRect方法和其他属性都是相同的。

如果我可以替换/继承UILabel和UITextView继承的UIView,那将是很棒的。然后我可以更改该公共子类中的drawRect代码,并添加UIView子类的新属性。但是,我不认为这是可能的(我希望是错的)。我已经考虑过简化drawRect方法中的代码,因此大多数都可以通过单独的函数来调用,这些函数可以包含在一个单独的类中,但仍然会留下属性。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

经过一些研究后,我发现实际上有一个解决方案允许您将方法实例变量(属性)添加到现有的框架类,如UIView

你需要两件事:

  1. 一个类别。 (Apple Docs: Detailed description
  2. 相关对象。 (Good example
  3. 通过类别,您可以将实例方法添加到现有类,但无法存储实例变量,即属性。幸运的是,有一个解决方法:您可以创建一个所谓的关联对象(存储在外部)并手动声明您的getter和setter方法:

    <强>的UIView + Background.h

    @interface UIView (Background)
    @property (nonatomic, copy) UIView *yourProperty;
    @end
    

    <强>的UIView + Background.m

    #import "UIView+Background.h"
    
    NSString *const propertyKey = @"yourPropertyKey";
    
    @implementation UIView (Background)
    
    - (void)setYourProperty:(UIView *)propertyValue {
        objc_setAssociatedObject(self, propertyKey, propertyValue, OBJC_ASSOCIATION_COPY);
    }
    
    - (UIView *)yourProperty {
        return objc_getAssociatedObject(self, propertyKey);
    }
    
    @end
    

    我还没有对此进行过测试,但它应该有效。

答案 1 :(得分:1)

大多数视图都是通过将它们放在视图层次结构中来合成的。考虑制作一个封装渐变代码的常规UIView子类,然后使用标准方法将它放在任何类型的视图下面(在IB中绘制,或者在代码中添加addSubview:)。

从这里你可以得到封装而不会违背语言。

编辑 - 重申一下,我建议您创建一个视图,其唯一的功能是绘制渐变,然后用其他视图组合。为了更清楚地撰写,我的意思是将它放在其他视图的下方(在某些父视图中使它们与具有匹配框架的兄弟姐妹,并使梯度视图首先以z顺序出现 - 在父视图的子视图数组中)。

parent view
  |
  --- gradient view (frame == parent view bounds)
  |
  --- UILabel (frame == parent view bounds, backgroundColor == [UIColor clearColor])

UILabel具有所有功能,只要您将其与渐变框架在一起,它也将具有渐变背景。如果你计划进行大量的重构,你当然可以为那个“父视图”创建一个特殊的UIView子类,它总是在另一个(参数)视图后面构建一个渐变,比如标签或文本字段或其他。