继承 vs 接口分类与接口生成器

3

我已经多次阅读到不能对组件(例如UIButton)进行子类化:

问题是当我使用Interface Builder时。 例如,我的很多视图中都有一个具有特定外观的按钮。我可以每次使用IB设置它们(这很痛苦),或者我可以使用自定义类来归纳定制行为和外观。

对我来说,唯一简化使用IB的方法似乎有些矛盾,因为推荐的做法是反过来的。

是否有更好的解决方案?我可以在IB中使用类别吗?

谢谢。

3个回答

3
你可以尝试使用UIView外观代理来实现。我不知道你对按钮做了哪些操作,但这个方法可能有帮助:
在AppDelegate文件的application:didFinishLaunchingWithOptions:方法中添加以下内容:
if([UIButton conformsToProtocol:@protocol(UIAppearanceContainer)]){
    [[UIButton appearance] setBackgroundImage:[UIImage imageNamed:@"YourImage"] forState:UIControlStateNormal];
    //modify any other UIButton properties you want to set globally
}

2
您提供的第二个链接非常清晰,这基本上就是苹果公司本身所说的,即子类化,但不要干扰内部结构。
最好的例子是iOS 7,现在情况完全不同,例如,我正在维护的一个应用程序有一个子类化的UIControl,现在在新的iOS上运行有问题,仅仅因为它是根据内部结构如何工作(迭代内部subviews替换某些内容)的假设构建的。您可能不会遭到拒绝,但维护将会很麻烦。
作为一个经验法则,您可以从外部对UIButton进行任何操作,像这样:
[myButton setBackgroundImage:... forState:...];
[myButton setTextColor:... forState:...];
myButton.titleLabel.font = ...

您可以将它移动到自定义子类方法的内部:
+ (UIButton*)fancyPantsButton
{
    UIButton *button = [UIButton butonWithType:UIButtonTypeCustom];

    [myButton setBackgroundImage:... forState:...];
    [myButton setTextColor:... forState:...];
    myButton.titleLabel.font = ...

    return button;
}

您也可以在initawakeFromNib上做到这一点,没有任何问题(我通常更喜欢后者)。

UIAppearence也是一个选项,正如用户hw731所建议的那样。真正有效的是什么,你自己决定。

至于第二个问题,nib文件基本上创建了一个类的实例,然后在加载时使用setValue:forKey:填充它存储的内容(这就是为什么当你弄坏了一个nib时会得到像“类不符合某些东西的键值对”的错误),所以如果在加载nib时对某些东西进行分类,那么是的,nibs将尊重分类,因为它只是使用initWithCoder..然后填补空白部分。

同样,除非在IB中的“User Defined Runtime Attributes”上显式添加它们,否则nib文件将无法填充自定义属性,因为它不知道它们。

nib的另一种技术是使用

@property (strong) IBOutletCollection(UIButton) NSArray *buttons;

然后根据需要迭代和自定义按钮(可以通过子类、类别、本地方法等方式)。如果您只想要一些自定义按钮,但不足以使用子类,则此方法非常有用。


不是完美的,但我会接受它。 - Matthieu Oger

2

我认为你完全可以继承UIButton类,特别是当你想要在IB中进行配置时。你提供的链接都没有解释为什么不应该这样做,所以它们的说法似乎不可靠。另一方面,UIButton.h文件中存在UIButtonTypeCustom,这给人的印象是框架作者为UIButton的子类做了准备。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接