4

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

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

我有 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
{
}

这样,一旦我对它进行了子类化,我只需将listivar 分配给我的数据结构。我什至可以重写方法,比如didFinishDeletingItem:自定义每个控制器的行为。

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

4

2 回答 2

3

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

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

    @interface CategoriesViewController : MyListViewController{

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

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

于 2013-09-08T03:36:48.457 回答
1

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

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

于 2013-09-08T07:21:25.797 回答