【问题标题】:Abstracting UIViewController like Cocoa ones [closed]像 Cocoa 一样抽象 UIViewController [关闭]
【发布时间】:2013-09-08 03:23:34
【问题描述】:

编辑:有人有关于这个主题的有用链接吗?我的意思是编写可重用代码和“抽象”的良好做法?

tl;dr - 阅读此评论 Abstracting UIViewController like Cocoa ones

我有 3 个UITableViewController:

  • CategoriesViewController
  • RecipesViewController
  • IngredientsViewController

它们是按层次排序的。下面是一个层次结构的例子:

  • 甜点(类)
    • 布朗尼(配方)
      • 牛奶(成分)
      • 巧克力(成分)
      • 黄油(成分)

其中每一个都具有与其他类似的功能。 例如,它们都有排序(移动行)、删除、添加(呈现模态视图)等。

目前,我已经为每个视图控制器重复了所有代码,以自定义与每个视图控制器相关的部分。例如,它们都有一个像这样的实例变量:

CategoriesViewController.m:

@implementation CategoriesViewController {
    NSMutableArray *categories;
}

RecipesViewController.m:

@implementation RecipesViewController {
    NSMutableArray *recipes;
}

IngredientsViewController.m:

@implementation IngredientsViewController {
    NSMutableArray *ingredients;
}

因为我认为有更好的方法来组织这个视图控制器,所以我尝试创建一个 MyListViewController.h 的骨架:

@interface MyListViewController : UITableViewController

@property (nonatomic, strong) NSMutableArray *list;

@end

MyListViewController.m:

@implementation MyListViewController

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_list count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ListCell"];

    id currentObject = [_list objectAtIndex:indexPath.row];
    cell.textLabel.text = [currentObject valueForKey:@"name"];

    return cell;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // get item to delete
        id object = [_list objectAtIndex:indexPath.row];

        // remove it from list
        [_list removeObjectAtIndex:indexPath.row];

        // call callback
        [self didFinishDeletingItem:object];

        // delete row from tableview
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

- (void)didFinishDeletingItem:(id)item
{
}

这样,一旦我对它进行了子类化,我只需将list ivar 分配给我的数据结构。我什至可以覆盖 didFinishDeletingItem: 之类的方法来自定义每个控制器的行为。

因为这是我第一次以这种方式使用编写和组织代码的最佳实践,所以我很想知道您的意见,以及哪些是抽象类以正确地重用它们的最佳方法DRY 原则。

【问题讨论】:

    标签: iphone ios objective-c design-patterns uiviewcontroller


    【解决方案1】:

    据我了解,您可以通过以下方式之一进行操作:

    1. 既然你说你的屏幕和行为是相同的,你可以使用同一个类 MyListViewController 并且在创建实例时你可以分配/填充“列表”数组。这是常规方法
    2. 或者,如果您的类(类别、食谱、成分)在行为上略有不同,您可以将它们子类到 MyListViewContrller。您可以像这样在 .h 文件中执行此操作:

      @interface CategoriesViewController : MyListViewController{

    在 Xcode 中,您也可以在创建新类文件时选择超类。

    希望这在某种程度上有所帮助

    【讨论】:

    • 我已经创建了 MyListViewController 的 tre 子类。现在我希望以适当的方式自定义每个人的行为。我应该在超类中使用像[self didFinishDoingSomething] 这样的大量自调用方法吗?阅读我在@Joride 答案中的评论以获取更多信息。泰!
    • 这个概念是这样的:所有通用行为(方法)和属性都应该在超类上(在你的例子中是 MyListViewController)。如果需要,可以为子类添加其他属性。附加行为将以两种不同的方式出现:a) 附加方法和 b) 在子类中覆盖相同的方法。覆盖是这个评论的一个稍微大的话题。我希望你在这方面保持同步。
    • 好的,谢谢。所以我尝试做的,在超类中调用[self didFinishDoingSomething] 之类的方法并在子类中覆盖相同的方法是精心设计的代码,好吧。
    【解决方案2】:

    (这应该是评论,但我还不能评论)。 不要做 [_列表计数]; 使用属性: [self.list 计数] 只能访问访问器中的 ivar,否则您将在沿线某处被咬。这也适用于您使用 _list 而不是 self.list 的其他地方。

    你的骨架类看起来不错,这是很好的编码。对此进行扩展:如果后面唯一的事情与项目的实际数据不同,您可以创建不同的 UITableViewCell 子类。 MyListViewController 可以查看 NSArray 中包含哪些类型的对象(或者您可以在 MyListViewCOntroller 上设置一个标志)并基于此使用适当的 UITableViewCell(从而正确显示数据。)

    【讨论】:

    • 您说“MyListViewController 可以看到 NSArray 中包含什么类型的对象”,但我不想为每个 UITableViewCell 类型硬编码 if 语句。我希望使MyListViewController 尽可能抽象,以便在我想要的时候重用它,而不会对类本身进行更改。我认为这就是 Cocoa-Touch 类的创建方式。您看不到这些类的实现,但由于它们的抽象,您几乎可以在所有情况下使用它们。
    • 是的。但这要求数据以相同的方式呈现。如果您想让演示文稿依赖于数据,则需要检查数据。尽管如此,你是对的。
    • 谢谢伙计。你有没有关于这个主题的一些有趣的参考资料(查看帖子更新)?
    • 一种有点不同的方法,但很有趣:cocoawithlove.com/2008/12/heterogeneous-cells-in.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    相关资源
    最近更新 更多