重用UIViewController子类我已经为非常相似但不完全相同的情况做了:推荐?

时间:2015-07-11 20:23:32

标签: ios objective-c uiviewcontroller

我仍然相对较新的iOS开发,并且想知道这是否是一个很好的做法。

例如,假设我有两种不同的上下文,我希望以相同/相似的方式呈现相同/相似的数据,但是存在一些差异,可能是从一个上下文到另一个上下文的不同按钮或我需要的不同内容做准备数据。我应该在同一个视图控制器中制作多个配置方法,并根据需要调用哪一个,或者有两个独立的视图控制器?

我非常倾向于前者是正确的,因为它看起来效率更高并且节省了大量相同的代码,但我希望得到更多有经验的程序员的一些意见以防万一。

3 个答案:

答案 0 :(得分:3)

您应该创建三个视图控制器:SuperViewControllerFirstViewControllerSecondViewControllerFirstViewControllerSecondViewController应该是SuperViewController的子类。那你应该考虑以下几点:

变量和属性

SuperViewController

中声明视图控制器之间的所有公共变量

在适当的视图控制器中声明任何视图控制器特定的变量和属性。

方法

与属性一样,在SuperViewController中定义任何共享方法及其实现。

如果您有一些方法可以在视图控制器之间共享一些代码,但不是全部,请执行以下操作:

1)在SuperViewController中实施此方法:

-(void)someSemiSharedMethod {
    // put the common code here
}

2)在你的视图控制器中:

-(void)someSemiSharedMethod {
    // call the superclass' implementation of this method
    // to ensure that common code is executed
    [super someSemiSharedMethod];

    // now add any child controller specific code to this method below
}

这种接缝就像是你想要实现的最佳方法。如果您有其他问题,或者这种方法无法完全达到您想要的效果,请告诉我。

答案 1 :(得分:3)

您可以执行Andriy描述的父超类方法,但还有另一种选择。

子类化非常强大,但有时难以推理。如果其中一个子视图控制器出现错误,则可能很难找出错误所在的位置。

如果视图控制器的自定义很小,您可以使用构造函数的参数表达它,例如:

- (instancetype)initWithSaveButton(BOOL)includeSaveButton;

或者,如果您需要自定义某些行为,请传递一个块:

- (instancetype)initWithSaveAction:(void (^)(Person *))saveAction;

如果定制是最小的,我发现这是一个比子类化更简洁的解决方案。

编辑:旁注,但是@leiyun问了一个关于BOOL标志的一个很好的问题 - 如果我们想要在按钮A和按钮B之间进行选择怎么办?我们应该设计一个像这样的init方法吗?

- (instancetype)initWithButtonA:(BOOL)includeA buttonB:(BOOL)includeB;

这是为什么应该避免使用BOOL标志的一个很好的例子。如果我们将此方法称为initWithButtonA:YES buttonB:YES,那么我们会进入未定义的行为,因为我们想在这些按钮之间选择

为此,请定义选项类型。

typedef enum {
    MyViewControllerModeNoButtons,
    MyViewControllerModeButtonA,
    MyViewControllerModeButtonB
} MyViewControllerMode;

- (instancetype)initWithMode:(MyViewControllerMode)mode;

这样的接口的指导原则是不应该是一种不正确的方式来调用它。此外,当您需要第三个按钮或图像视图或其他内容时,这将更好地容纳更多选项!

答案 2 :(得分:2)

为了完整起见,我想在Andriy和joerick的答案之后提出我认为的第三种选择,特别是对于" 我需要做的不同的事情准备数据" -scenario:实际上为两个屏幕使用相同的视图控制器类,但为保存,准备和提供适当数据的每个上下文创建单独的数据源对象。

这些数据源对象可以是简单的NSObject子类,符合协议。对于显示数据的常用方法,已经有预定义的数据源协议,例如 UITableViewDataSource UICollectionViewDataSource 。如果那些不适合您的需求,您当然可以定义自己的协议。数据源可以由视图控制器实例作为属性保存,如下所示:

@property (strong, nonatomic) id<UITableViewDataSource> myDataSource;

你可以&#34;给&#34;初始化时视图控制器的相应数据源,例如

-(instancetype)initWithDataSource: (id<UITableViewDataSource>) dataSource