UIViewController 子类调用方法

Posted

技术标签:

【中文标题】UIViewController 子类调用方法【英文标题】:UIViewController subclass calling methods 【发布时间】:2014-01-31 01:12:18 【问题描述】:

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

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

我希望用户能够控制他们在这个方法中所做的事情,所以我认为他们应该在他们的子类中实现它:

- (void)showPicker 
    // Do what you want

为了做到这一点,我不得不在我原来的UIViewController中添加一个同名的空白方法,然后也将它添加到头文件中。

我想要做的就像你可以继承 UIViewController 然后实现 viewWillAppear: 并在该方法中做你想做的事。

如果我想允许用户控制当我的班级内的按钮被点击时会发生什么,这是否是正确的模式?我做这一切都错了吗?我应该使用委托吗?

【问题讨论】:

【参考方案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

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

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

【讨论】:

优秀的答案!我想我会坚持使用空方法,因为它只是我需要使用的一种方法。再次感谢!【参考方案2】:

创建一个设计为子类的类是可行的,而且没有错(大多数框架都依赖于这样的类)。这是否实际上是您的最佳选择取决于您期望如何使用该类。

子类化在以下情况下有意义:

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

另一方面,如果满足以下条件,委托可能是更好的选择:

此行为是可选的。 消息属于不属于发送类职责的问题的一部分。也许控制器已经确定了用户的意图(“选择此选项”),但根据该意图采取行动并不是它的工作。请注意,如果合适的话,一个对象可以是它自己的委托(例如,为一个 nil 委托提供默认行为而不是默认行为。) 一个对象从多个来源响应此消息是合理的。 重要的是不要覆盖发送对象的行为。尽管“必须调用 super”在 UIKit 中出现的次数很多,但它并不是一个好的模式。

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

【讨论】:

以上是关于UIViewController 子类调用方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从 UIView 子类调用 UIViewController?

动态子类化 UIViewController 的错误

如何在子类中调用 UIViewController 的函数?

drawRect 在 UIView 子类上被调用,但不在 UIViewController 上

从 UIViewController 方法更改 UIWindow 的呈现视图

从 UIViewController 调用自定义 UINavigationController 中的方法时目标错误