MVC — ключевая часть хорошего проектирования на Cocoa. Приложения, использующие MVC, также более легко расширяемы, чем другие приложения. Кроме того, много технологий и архитектур Cocoa основываются на MVC и требуют, чтобы ваши пользовательские объекты играли одну из ролей MVC.
В MVC существует 3 роли:
- Model: объект, который содержит данные приложения и определяет, как управлять ими.
- View: объекты, которые отвечают за визуальное представление модели и пользовательские манипуляции. Представлениями, в основном, являются все UIView-производные объекты.
- Controller: контроллер-посредник, который координирует всю работу. Он получает доступ к данным модели и выводит их на экран с помощью представления, следит за событиями и управляет данными по мере необходимости.
Правильная реализация паттерна MVC означает, что в вашем приложении каждый объект попадает только в одну из этих групп. Как показано на схеме.
Чтобы всё это применить на практике, напишем тестовое приложение для просмотра списка книг.
Выделим наши три основных составляющих:
- Модель — книга, у которой будут поля: название, автор, цена;
- Представление — это само отображение наших данных, мы их будем отображать их в таблице;
- Контроллер — это наш координатор между моделью и нашим представлением.
Создаём новый файл для нашей модели с названием Book.
В заголовочном файле Book.h пропишем свойства и метод инициализации.
//Book.h
@interface Book : NSObject
@property (strong, nonatomic) NSString* name; //Название книги
@property (strong, nonatomic) NSString* author; //Автор книги
@property (assign, nonatomic) CGFloat price; //Цена книги
- (id) initWithName:(NSString*) name author:(NSString*) author price:(CGFloat) price; //Метод инициализации нашего объекта Book
@end
В файле реализации Book.m опишем наш метод.
//Book.m
#import "Book.h"
@implementation Book
- (id) initWithName:(NSString*) name author:(NSString*) author price:(CGFloat) price {
self = [super init];
if(self) {
self.name = name;
self.author = author;
self.price = price;
}
return self;
}
@end
Для управления книгами и их данными создадим синглтон. Разбирать подробно его в данной статье мы не будем, но я дам небольшое описание, это класс у которого существует единственный экземпляр и предоставляющий к нему глобальную точку доступа.
Создаём новый файл с названием BookManager.
В заголовочном файле BookManager.h пропишем свойства и метод инициализации.
//BookManager.h
@class Book;
@interface LibraryManager : NSObject
@property (strong, nonatomic) NSArray* books; //Массив из всех наших книг
+ (id) sharedInstance;
@end
В файле реализации LibraryManager.m мы описываем метод инициализации, а так же заполним небольшим количество данных наш массив books.
//BookManager.m
#import "LibraryManager.h"
#import "Book.h"
@implementation LibraryManager
+ (id) sharedInstance {
static Book* sharedInstance = nil; //статическая переменная для хранения указателя на объект класса
static dispatch_once_t onceToken; //статическая переменная, обеспечивающая выполнение кода инициализации единожды
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init]; //блок инициализации
});
return sharedInstance;
}
- (instancetype)init //В данном методе мы заполняем наш массив книг
{
self = [super init];
if (self) {
self.books = [NSMutableArray arrayWithArray:
@[[[Book alloc] initWithName:@"Harry Potter and the Sorcerer's Stone"
author:@"Joanne Rowling"
price:10.f],
[[Book alloc] initWithName:@"Война и мир"
author:@"Лев Толстой"
price:13.f],
[[Book alloc] initWithName:@"The Old Man and the Sea"
author:@"Ernest Hemingway"
price:8.4f]]];
}
return self;
}
@end
Далее откроем наш Main.storyboard, удалим имеющийся там ViewController и создадим NavigationController.
Выберем наш NavigationController и установим ему свойство isInitialViewController в Attributes Inspector, как показано на рисунке.
Создадим новый файл для нашего контроллера, назовём его BookViewController, наследник UIViewController. Откроем файл BookViewController.m. Для отображения наших данных в таблице нам необходимо:
- Задать количество секций в нашей таблице (по умолчанию 1);
- Задать количество ячеек в нашей таблице, у нас их будет столько сколько книг в нашей библиотеке;
- Ну и конечно отрисовка самой ячейки.
//BookViewController.m #import "BookTableViewController.h" #import "LibraryManager.h" #import "Book.h" @interface BookTableViewController () @end @implementation BookTableViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark - UITableViewDataSource //количество секция в нашей таблице
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; }
//Считаем какое количество ячеек нужно отрисовать для нашей секции (секций в нашем случае 1) - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[[LibraryManager sharedInstance] books] count]; } //Рисуем наши ячейки, - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //Идентификатор нашей ячейки static NSString* identifier = @"Cell"; //Создаем ячейку из нашей таблицы по заданному идентификатору UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; //Если такой ячейки ещё нет, то создаем новую if(!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier]; } //Заполняем поля нашей ячейки cell.textLabel.text = [[[[LibraryManager sharedInstance] books] objectAtIndex:indexPath.row] name]; cell.detailTextLabel.text = [NSString stringWithFormat:@"%f", [[[[LibraryManager sharedInstance] books] objectAtIndex:indexPath.row] price]]; return cell; } @end
Осталось сделать последний штрих. Нам надо присвоить класс нашему Root View Controller в нашем сториборде как показано на рисунке.
Ну и наконец мы можем запустить наше приложение и убедиться что оно работает.
Исходный код данного примера: alhafram/mvcExample
Автор фото: @madeawkward
Спасибо за внимание.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.