Подтвердить что ты не робот

Как работать с классами моделей в приложении iOS

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

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

  • Многие говорят, что нужно написать свойство делегата приложения для хранения модели, а затем ссылаться на нее с помощью удобных методов для делегата делегата приложения.
  • другие говорят, что "вводят" в контроллер представления только часть модели, которая ему нужна (или ее потребности в подзаголовках), но я не понимаю, как это сделать. Через собственность? С помощью метода initWithModel: (и в этом случае, как я могу сказать IB, чтобы использовать этот метод?)
  • другие снова говорят, что модель должна быть singleton
  • и снова, другие говорят, что используют глобальные переменные (!)

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

4b9b3361

Ответ 1

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

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

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

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

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

  • Модель создается или загружается делегатом приложения как объект NSMutableArray для продукта;
  • Указатель на модель теперь передается в первый контроллер представления нашей иерархии 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 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

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

Ответ 2

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

Ответ 3

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

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

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

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

Что мне не нравится:

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

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

Четыре.?!?!