2013-09-08 3 views
4

EDIT: Есть ли у кого-то, кто имеет полезные ссылки по этой теме? Я имею в виду хорошие практики написания многоразового кода и «абстракции»?Abstracting UIViewController как какао

Т.Л., др - прочитать этот комментарий Abstracting UIViewController like Cocoa ones

У меня есть 3 UITableViewController:

  • CategoriesViewController
  • RecipesViewController
  • IngredientsViewController

Они иерархически. Ниже приведен пример иерархии:

  • Десерт (категория)
    • Домовой (рецепт)
      • Молоко (ингредиент)
      • Шоколад (ингредиент)
      • масло (ингредиент)

enter image description here

Каждый из них имеет аналогичные функциональные возможности с другими. Например, у всех их есть сортировка (перемещение строк), удаление, добавление (представление модального вида) и т. Д.

В настоящее время я повторил весь код для каждого контроллера вида, который настраивает части, относящиеся к каждому из них. Например все они имеют переменную экземпляра так:

CategoriesViewController.m:

@implementation CategoriesViewController { 
    NSMutableArray *categories; 
} 

RecipesViewController.m:

@implementation RecipesViewController { 
    NSMutableArray *recipes; 
} 

IngredientsViewController.m:

@implementation IngredientsViewController { 
    NSMutableArray *ingredients; 
} 

Потому что я думаю, что есть лучший способ организовать этот контроллер представления Я попытался создать ske leton из 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 Ивар моей структуры данных. И я могу даже переопределить методы, такие как didFinishDeletingItem: для настройки поведения каждого контроллера.

Потому что это первый раз, когда я хотел бы использовать лучшие практики написания и организацию коды таким образом, я хотел бы знать ваше мнение, и которые являются лучшим способом для абстрактных классов для многократного использования их правильно после DRY принципа.

ответ

1

(Это должно быть комментарий, но пока я не могу комментировать). Не делать [_list count]; Используйте этот объект: [self.list count] Только доступ к ivar в аксессуарах, или вас укусят где-нибудь вдоль линии. Это также касается других мест, в которых вы используете _list вместо self.list.

Ваш класс скелета выглядит нормально, и это хорошее кодирование. Расширяясь на этом: если в реальных данных для элементов будет только одно другое, вы можете создать различные подклассы UITableViewCell. MyListViewController может видеть, какие типы объектов содержатся в NSArray (или вы можете установить флаг в MyListViewCOntroller) и использовать на этом основании соответствующий UITableViewCell (и, следовательно, правильно отображать данные.)

+0

Вы сказали, что «MyListViewController может видеть, какие типы объектов содержатся в NSArray», но я не хочу жестко кодировать инструкции if для каждого типа 'UITableViewCell'. Я хочу сделать «MyListViewController» максимально абстрактным, чтобы повторно использовать его, когда захочу, и БЕЗ внесения изменений в самом классе. Я думаю, что именно так создаются классы Cocoa-Touch. Вы не можете видеть реализацию этих классов, но вы можете использовать их практически для каждой ситуации, благодаря их абстракции. –

+0

Правда. Но для этого необходимо, чтобы данные были представлены таким же образом. Если вы хотите, чтобы представление зависело от данных, вам нужно будет проверить данные. Тем не менее, вы правы. – Joride

+0

Спасибо человеку. Были ли у вас интересные ссылки по этой теме (проверить обновление сообщений)? –

3

Из того, что я понимаю, что вы можете сделать это одним из следующих способов:

  1. Поскольку вы сказали ваши экраны и поведение одинаковы, вы можете использовать один и тот же класс MyListViewController и при создании экземпляра, может назначить/заполнить массив «list». Это обычный подход
  2. В качестве альтернативы, если ваши классы (категории, рецепты, ингредиенты) немного отличаются по своему поведению, вы можете подклассифицировать их в MyListViewContrller. Вы можете сделать это в файле .h, как это:

    @interface CategoriesViewController: MyListViewController {

В Xcode, вы можете выбрать супер-класса, а создавать новый файл класса тоже.

Надеется, что это помогает в некотором роде

+0

Я уже создал tre подклассы 'MyListViewController'. Теперь я хочу правильно настроить поведение каждого из них. Должен ли я использовать массовые методы самонаведения, такие как '[self didFinishDoingSomething]' в суперклассе? Прочитайте мой комментарий в ответе @Joride для получения дополнительной информации. Ty! –

+1

Концепция такова: все общие поведения (методы) и свойства должны быть на суперклассе (в вашем случае MyListViewController). Дополнительные свойства могут быть добавлены для подклассов, если это необходимо. Дополнительное поведение будет осуществляться двумя разными способами: а) дополнительные методы и б) одинаковые методы, переопределяющие в подклассах. Переопределение - немного большая тема для этого комментария. Надеюсь, вы синхронизировали это. – zolio

+0

Хорошо, спасибо. Итак, что я пытался сделать, вызывая метод, подобный '[self didFinishDoingSomething]' в суперклассе и переопределяя тот же метод в подклассе, хорошо продуманный код, хорошо. –

Смежные вопросы