Как бороться с модельными классами в iOS-приложении - PullRequest
17 голосов
/ 24 августа 2011

Я новичок в разработке приложений для iOS, но я пытаюсь узнать, как лучше всего обращаться с Какао.

Я застрял, пытаясь понять, как правильно хранить и ссылаться на объекты модели.

  1. многие говорят, что пишут свойство делегата приложения для хранения модели, а затем ссылаются на него с помощью удобных методов для одноэлементного делегата приложения.
  2. другие говорят «ввести» в представленииКонтроллер только та часть модели, которая ему нужна (или нуждается в ее подпредставлениях), но я не понимаю, как это сделать.Через собственность?Через initWithModel: метод (и в этом случае, как я могу сказать IB, чтобы использовать этот метод?)
  3. другие снова говорят, что модель должна быть одиночной
  4. , и снова, другие говорятиспользовать глобальные переменные (!)

Не могли бы вы дать мне подсказку (и примеры кода)?Я хотел бы изучить все правильно, учитывая, что скоро я буду двигаться к Базовым данным.

Ответы [ 3 ]

12 голосов
/ 26 августа 2011

Аннотация : я внимательно прочитал тему Где разместить «базовый стек данных» в приложении Cocoa / Cocoa Touch , предложенное Брэдом Ларсоном, и я написал возможное решение о том, как иметь дело с моделью и различными контроллерами представления. Решение не использует Core Data, но я считаю, что тот же дизайн может быть применен к приложениям Core Data.

Сценарий : давайте рассмотрим простое приложение, которое хранит информацию о продуктах, такую ​​как название, описание и цена / единица. После запуска приложение отображает список продуктов (с UITableView); когда пользователь нажимает на название продукта, приложение отображает сведения о продукте в другом представлении, обновляя панель навигации названием продукта.

Архитектура Здесь модель довольно проста: массив объектов Product, каждый из которых имеет имя, описание и свойство цены.

Приложение имеет три основных вида, в основном создаваемых шаблоном навигации XCode: UINavigationView (управляемый UINavigationController, создается в делегате приложения), UITableView по умолчанию (управляемый RootViewController и являющийся первым представлением, отображаемым UINavigationController) и DetailView (управляемый классом DetailViewController, который мы должны написать).

Давайте посмотрим, что представляет собой большой план с точки зрения модели:

  1. Модель создается / загружается делегатом приложения как NSMutableArray объектов Product;
  2. Указатель на модель теперь передается первому контроллеру представления нашей иерархии, UITableViewController, через свойство. На самом деле, можно утверждать, что первым контроллером в иерархии является UINavigationController, поэтому мы должны передать ссылку на него и из него на UITableViewController, но ... Apple говорит, что UINavigationController не должен иметь подклассы, поэтому мы не можем добавить какое-либо свойство / метод. И на самом деле это имеет смысл, потому что ответственность UINavigationController - это всегда только управление визуализацией, а не манипулирование моделью.
  3. Когда пользователь выбирает UITableCell, UITableViewController создает новый DetailViewController (со связанным DetailView), передает один выбранный продукт в качестве свойства и помещает DetailView на вершину стека UINavigation.

Вот некоторые фрагменты кода:

Создание модели:

// SimpleModelAppDelegate.m    

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // products is a protected ivar
    products = [[NSMutableArray alloc] init];

    Product *p1 = [[Product alloc] initWithName:@"Gold" andDescription:@"Expensive metal" andUnitPrice:100];
    Product *p2 = [[Product alloc] initWithName:@"Wood" andDescription:@"Inexpensive building material" andUnitPrice:10];

    [products addObject:p1];
    [products addObject:p2];

    [p1 release];
    [p2 release];

    // Passing the model reference to the first shown controller 
    RootViewController *a = (RootViewController*)[self.navigationController.viewControllers objectAtIndex:0];
    a.products = products;

    // Add the navigation controller's view to the window and display
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)dealloc
{
    // The app delegate is the owner of the model so it has to release it.
    [products release];
    [_window release];
    [_navigationController release];

    [super dealloc];
}

RootViewController может получить ссылку на модель, поскольку он имеет свойство NSMutableArray:

// RootViewController.h

#import <UIKit/UIKit.h>

@interface RootViewController : UITableViewController

@property (nonatomic, retain) NSMutableArray *products;

@end

Когда пользователь нажимает на название продукта, RootViewController создает новый экземпляр DetailViewController и передает ему ссылку на отдельный продукт, снова используя свойство.

// RootViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];

    // Passing the model reference...
    detailViewController.product = [products objectAtIndex:indexPath.row];

    [self.navigationController pushViewController:detailViewController animated:YES];

    [detailViewController release];
}

И, наконец, DetailViewController показывает информацию о модели, устанавливающей свои выходы в методе viewDidLoad.

// DetailViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.title = product.name;
    self.descriptionLabel.text = product.description;
    self.priceLabel.text = [NSString stringWithFormat:@"%.2f eur", product.unitPrice];
}

Вы можете скачать полный проект здесь: http://dl.dropbox.com/u/1232650/linked/stackoverflow/SimpleModel.zip

Я буду очень признателен за любые комментарии к моему решению, я хочу учиться;)

1 голос
/ 07 декабря 2011

Более опытные коллеги рекомендуют иметь соответствующую недвижимость в AppDelegate.ИМО лучше использовать определенный набор моделей в конкретном контроллере.

0 голосов
/ 24 августа 2011

Я тоже нуб, но вот что я сделал.Это больше похоже на # 2.

В applicationDidFinishLaunching делегат приложения создает экземпляр модели.

Мои контроллеры представления объявляют свойство, указывающее на модель, но тип является протоколом (вВ моем случае id <GameModel>. Многие свойства в протоколе объявлены как доступные только для чтения.

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

Что я делаюо:

1. Ваши контроллеры представления не должны знать о структуре вашего делегата приложения. Вы можете повторно использовать тот же контроллер представления в другом приложении с другим типом делегата приложения.внесите простые изменения в код контроллера представления, чтобы это исправить, или есть другие способы обойти это, но зачем делать это сложно?

Три. Я не так люблю одиночные игры, как большинство людей. Проблема в том,они одиноки. Что если вы хотите загрузить несколько моделей?

Четыре.?!?!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...