UIViewController子类调用方法

时间:2014-01-31 01:12:18

标签: ios objective-c cocoa-touch uiviewcontroller delegates

我构建了一个实现各种UI功能的UIViewController。它旨在供用户进行子类化,以便他们可以使用setContents:getContents等几种方法对其进行更新。

在我的UIViewController中,当我点击一个我希望用户在其子类showPicker中实现的按钮时,我正在调用方法。

我希望用户能够控制他们在此方法中执行的操作,因此我认为他们应该只在子类中实现它:

- (void)showPicker {
    // Do what you want
}

为了做到这一点,我必须在原始UIViewController中添加一个同名的空白方法,然后将其添加到头文件中。

我想要做的就是如何创建UIViewController的子类,然后实现viewWillAppear:并在该方法中执行您想要的操作。

如果我想让用户控制点击班级里面的按钮会发生什么,这是正确的模式吗?我做错了吗?我应该使用代表吗?

2 个答案:

答案 0 :(得分:1)

如果您想模仿UIViewControllerviewWillAppear:所做的事情,则需要在基类中添加showPicker的无操作实现。 UIViewController.h表示viewWillAppear:的默认实现不执行任何操作。

委托会使你的基类和子类复杂化,而不会真正简化回复。它们非常接近通知而非抽象方法。

这里的其他选择是做一些事情:

if ([self canPerformSelector:@selector(showPicker)]) {
  ...
}

它没有为我的喜好提供尽可能多的编译时安全性,但它是一种替代方案,并且在基类中保留了大部分责任。但我发现它不像基类中的空方法实现那样可被发现。

如果您不希望基类中的抽象方法实现空实现,那么协议可能更适合,平衡可发现性和编译时安全性。

@protocol PickerProtocol <NSObject>
- (void)showPicker;
@end

@interface SomeBaseClass : UIViewController
  ...
@end

@implementation SomeBaseClass

- (void)someBaseClassMethod {
  if ([self conformsToProtocol:@protocol(Picker)]) {
    [(id<PickerProtocol>)self showPicker];
  }
}

@end

您的子类通过声明已实现协议来选择加入,允许编译器在您未实现所有@required方法时发出警告。

@interface MySubClass <PickerProtocol>
  ...
@end

@implementation MySubClass

- (void)showPicker {
  ...
}

@end

这允许编译器显示警告和代码完成。虽然它不像空基类方法那么简单,但它确实允许子类明确声明它们提供了某些行为。

如果只是这里或那里的方法,我会使用空方法。如果你有一组应该一起实现的方法,我会使用协议。

答案 1 :(得分:1)

创建一个设计为子类的类将起作用并且没有错(大多数框架依赖于这些类)。这是否真的是最适合您的选择取决于您对课程的使用方式。

如果符合以下条件,则子类化是有意义的:

  • 您想提供这些方法的默认实现。
  • 您希望子类能够通过控制if和何时调用super来覆盖和替换默认实现。
  • 此消息仅与接收类相关,例如,如果生成的操作通常与控制器私有方法或属性交互。将其暴露于其他物体会引入它们之间的紧密耦合并违反单一责任原则。

另一方面,如果出现以下情况,代表可能是更好的选择:

  • 此行为是可选的。
  • 该消息是关注的一部分,而不是发送类的责任。也许控制器已确定用户意图(“选择此选项”),但对该意图采取行动不是它的工作。请注意,对象可以是适当的委托(例如,提供默认行为而不是默认为nil委托。)
  • 一个对象从许多来源回复此消息是合理的。
  • 重要的是不要覆盖发送对象的行为。尽管UIKit出现了多次,但“必须打电话给超级”并不是一个好的模式。

块也可能非常适合接受小单位的自定义行为,而无需额外的类。