Аннотация : я внимательно прочитал тему Где разместить «базовый стек данных» в приложении Cocoa / Cocoa Touch , предложенное Брэдом Ларсоном, и я написал возможное решение о том, как иметь дело с моделью и различными контроллерами представления. Решение не использует Core Data, но я считаю, что тот же дизайн может быть применен к приложениям Core Data.
Сценарий : давайте рассмотрим простое приложение, которое хранит информацию о продуктах, такую как название, описание и цена / единица. После запуска приложение отображает список продуктов (с UITableView); когда пользователь нажимает на название продукта, приложение отображает сведения о продукте в другом представлении, обновляя панель навигации названием продукта.
Архитектура Здесь модель довольно проста: массив объектов Product, каждый из которых имеет имя, описание и свойство цены.
Приложение имеет три основных вида, в основном создаваемых шаблоном навигации XCode: UINavigationView (управляемый UINavigationController, создается в делегате приложения), UITableView по умолчанию (управляемый RootViewController и являющийся первым представлением, отображаемым UINavigationController) и DetailView (управляемый классом DetailViewController, который мы должны написать).
Давайте посмотрим, что представляет собой большой план с точки зрения модели:
- Модель создается / загружается делегатом приложения как NSMutableArray объектов Product;
- Указатель на модель теперь передается первому контроллеру представления нашей иерархии, UITableViewController, через свойство. На самом деле, можно утверждать, что первым контроллером в иерархии является UINavigationController, поэтому мы должны передать ссылку на него и из него на UITableViewController, но ... Apple говорит, что UINavigationController не должен иметь подклассы, поэтому мы не можем добавить какое-либо свойство / метод. И на самом деле это имеет смысл, потому что ответственность UINavigationController - это всегда только управление визуализацией, а не манипулирование моделью.
- Когда пользователь выбирает 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
Я буду очень признателен за любые комментарии к моему решению, я хочу учиться;)