Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 重用UIViewController子类I';我们针对非常相似但不完全相同的情况制定了:推荐?_Ios_Objective C_Uiviewcontroller - Fatal编程技术网

Ios 重用UIViewController子类I';我们针对非常相似但不完全相同的情况制定了:推荐?

Ios 重用UIViewController子类I';我们针对非常相似但不完全相同的情况制定了:推荐?,ios,objective-c,uiviewcontroller,Ios,Objective C,Uiviewcontroller,我对iOS开发还比较陌生,我想知道这样做是否是一个好的实践 例如,假设我有两个不同的上下文,在其中我想以相同/相似的方式呈现相同/相似的数据,但是存在一些差异,可能是从一个上下文到另一个上下文的一些不同按钮,或者我需要做不同的事情来准备数据。我应该在同一个视图控制器中创建多个配置方法并根据需要调用其中一个,还是使用两个单独的视图控制器 我非常倾向于前者是正确的,因为它看起来效率更高,并且保存了很多相同的代码,但我希望有经验的程序员提供一些输入,以防万一。您应该创建三个视图控制器:SuperVie

我对iOS开发还比较陌生,我想知道这样做是否是一个好的实践

例如,假设我有两个不同的上下文,在其中我想以相同/相似的方式呈现相同/相似的数据,但是存在一些差异,可能是从一个上下文到另一个上下文的一些不同按钮,或者我需要做不同的事情来准备数据。我应该在同一个视图控制器中创建多个配置方法并根据需要调用其中一个,还是使用两个单独的视图控制器


我非常倾向于前者是正确的,因为它看起来效率更高,并且保存了很多相同的代码,但我希望有经验的程序员提供一些输入,以防万一。

您应该创建三个视图控制器:
SuperViewController
FirstViewController
SecondViewController
FirstViewController
SecondViewController
应该是
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
}

这是实现您想要的目标的最佳方法。如果您还有其他问题,或者这种方法没有完全达到您的要求,请告诉我。

您可以使用Andrey描述的父超类方法,但还有另一种选择

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

如果视图控制器的自定义值很小,则可以使用构造函数的参数来表示,例如:

- (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;

这样的接口的指导原则是,不应该有错误的方式来调用它。此外,当您需要第三个按钮或图像视图或其他东西时,这将更好地容纳更多选项 这些数据源对象可以是简单的NSObject子类,符合协议。对于显示数据的常用方式,已经为数据源预定义了协议,如UITableViewDataSource和UICollectionViewDataSource。如果这些不适合您的需要,您当然可以定义自己的协议。数据源可以作为属性由视图控制器实例持有,如下所示:

@property (strong, nonatomic) id<UITableViewDataSource> myDataSource;
@property(强,非原子)id myDataSource;
您可以在初始化时将适当的数据源“提供”给视图控制器,例如

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

我同意。使用继承将是正确的处理方法(尽管“父”和“子”VCs可能不是最好的名称,因为它们通常都是这样)。通过这种方式将它们分开,可以使每个控制器更纤细,更易于测试和维护。此外,它们之间的区别(以及共同部分!)对于将来需要阅读您的代码的人来说将立即变得显而易见。@Gamma您是对的,我可能应该更改命名:)是的,这也是一种很好的方法。这一切都取决于所需的定制量。在使用构造函数的参数表示定制时,处理我想要按钮X或按钮Y的情况的最佳方法是什么?执行“initWithXButton:(bool)includeXButton”之类的操作似乎有点尴尬,如果includeXButton为false,则包含按钮Y。您也可以使用专门的构造函数,而不是bool,例如“initForContext1”和“initForContext2”方法。好的,很酷。我想最好在构造函数中指定差异。在做了[[vc alloc]init]之后,我最初做的是类似于[vc configureForX]的事情,经过进一步思考,这似乎是一个非常糟糕的设计。@leiyun问得好!我只是编辑了我的答案以提供我的回答。