【问题标题】:When is it acceptable to reduce code duplication by placing the code in AppDelegate?什么时候可以通过将代码放在 AppDelegate 中来减少代码重复?
【发布时间】:2017-10-01 14:35:50
【问题描述】:

我有一个非常小的 Xcode 项目,其中包含多个视图控制器。我发现自己在其中复制了以下方法:

- (void)postTip:(NSString *)message {
    [self postInfoAlertWithTitle:@"Tip" andMessage:message andAction:@"Got it!"];
}

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:action style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

当然,这让我开始思考如何删除(或至少减少)重复的代码。

显而易见的答案是将所需的行为放在父类中,然后让我的视图控制器从该类继承。但是,一些视图控制器是 UICollectionViewController 类型,有些是 UITableViewController 类型,如果我让它们从假设的 MyViewController is-a 继承,我不知道如何分别保留它们的集合和表风格UIViewController。

所以我做了一些研究并查看了协议。最初,这似乎很合适,只是您不能为协议中声明的方法提供默认实现,这基本上是我想要的。

最后,在犹豫不决和自我厌恶的情况下,我考虑将行为放在我的 AppDelegate 类中,并带有一个附加参数以方便呈现警报:

- (void)postTip:(NSString *)message toController:(UIViewController *)controller;
- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action toController:(UIViewController *)controller;

给定视图控制器中的调用如下所示:

[self.appDelegate postTip:@"Git gud!" toController:self];

瞧!我想要的行为、我想要的行为以及我所要做的就是获得 AppDelegate 的一个实例!但是……这对我不利。好像……很臭。此外,还有一些重复,即声明和初始化一个私有 appDelegate 属性,我已经小心地这样做了,而不是在我需要的地方调用 (AppDelegate *)[[UIApplication sharedApplication] delegate] 以便:

  • 我可以指定“弱”并避免可能的保留周期
  • 我只使用一个指向 AppDelegate 的指针(为过早的优化欢呼>.

将 AppDelegate 用作应用程序范围行为(例如实用程序方法)的存储库是否被认为是可以接受的,如果是这样,我是否对实现 re: 使用属性感到不必要的偏执? (如果没有,我有什么选择?)

【问题讨论】:

  • UIViewController 上创建一个类别,该类别将具有方法(初始方法,而不是 AppDelegate 方法)。 UICollectionViewControllerUITableViewController 继承自 UIViewController,所以应该没问题。避免像这样使用您的 AppDelegate 添加太多不相关的信息。您在现实中使用的是事实是它是一个单例(可以自己制作)。
  • 您可以创建一个“TipHelper”类并在您的各种控制器中使用该类的实例(或共享实例)。由于继承对您来说不是一个简单的选择,因此组合是另一种可用的策略。
  • Larme - 啊,我不知道类别!非常有趣,而且,我认为,只是门票!
  • Phillip - 嗯,是的,这也是一个很好的建议:基本上用辅助类替换 AppDelegate 的实例。我应该提到我之前已经想到了这一点,但决定反对它,因为我最终为每个控制器实现了参数化的 init 方法,以保持事物解耦(而尝试与 AppDelegate 解耦是没有意义的)。鉴于使用新的 init 方法有更多的本质上“重复”的代码,我认为使用 AppDelegate 更容易。可以用任何一种方式提出论点,但我同意您的建议更简洁。
  • 正如你所说,你有 BaseViewController 同样你可以创建 BaseCollectionViewControllerBaseTableViewController 继承 BaseViewController 而不是 UIViewController 并像使用 UIViewController 一样使用两者,所有方法都将遵循,这个更简洁的方法是创建类别而不是创建类别,因为它也允许您定义属性,并避免使用AppDelegate,因为它不会自我破坏,因此您最终可能会吃掉内存。

标签: ios objective-c uiviewcontroller duplicates appdelegate


【解决方案1】:

通过创建 .h 和 .m 文件来确定使用类别

UIViewController+InfoAlert.h

@interface UIViewController (InfoAlert)

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action;

@end

UIViewController+InfoAlert.m

#import "UIViewController+InfoAlert.h"

@implementation UIViewController (InfoAlert)

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:action style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

@end

然后只需将您的 UIViewController+InfoAlert.h 导入您想要使用新 postInfoAlertWithTitle 方法的位置

【讨论】:

    【解决方案2】:

    在我看来,类别正是针对这种情况而设计的——尽管正如其他人在 cmets 中指出的那样,还有其他选择——这就是我所做的。

    要查看 Apple 的类别文档,请参阅 this page。 要在 Xcode 中添加类别,请参阅this page

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      相关资源
      最近更新 更多