При разработке под Mac OS и iOS важнее знать структуру фреймворков, чем всё остальное. Основываясь на этом знании вы изменяете несколько строк кода для того чтобы реализовать то что вам нужно. Основная идея процесса разработки под Mac OS и iOS это автоматизация процесса разработки. Фреймворки выполняют большую часть работы.
Вверху экрана содержится navigation bar. Для того чтобы добавить новый элемент в таблицу нужно коснуться +.
Если нажать на серый индикатор раскрытия, то откроется детальный вид (обратите внимание что тут вместо table view обычный simple view):
Чтобы вернуться назад нужно нажать на Master (введенные данные сохранятся):
Проверка:
Если на master view нажать кнопку Edit то появится следующий вид:
navigation bar разделяют редактирование структуры (добавление, удаление, и перестановка экземпляров) и редактирование данных (например, смена наименования).
Удаление данных:
Создадим новое iOS приложение по Master-Detail шаблону.
Изменим модель данных:
Изменим код:
a) Change the Attribute for the Sort Descriptor
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@”name” ascending:NO];
b) Change valueForKey in configureCell
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath
*)indexPath
{
NSManagedObject *managedObject = [self.fetchedResultsController
objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:@”name”] description];
}
c) Change setValue: forKey:
// If appropriate, configure the new managed object.
// Normally you should use accessor methods, but using KVC here avoids the
// need to add a custom class to the template.
[newManagedObject setValue:[NSDate date] forKey:@”timeStamp”];
Откроем в Assistant Editor-е файлы DetailViewController_iPhone.xib и DetailViewController.h:
Удалим label из nib файла. Перетащите text field на DetailViewController_iPhone.xib. Хорошей практикой является сразу указывать метку для новых объектов. Создадим outlet в файле DetailViewController.h.
Также добавьте текстовое поле для адреса и создайте свойство для него.
Для того чтобы сохранять данные нужно:
- При показе detail view, переместить данные из атрибута name в текстовое поле.
- При выходе с detail view, переместить данные из текстового поля в атрибут name.
- Сохранить managed object context.
Тут помогут методы viewWillAppear и viewWillDisappear.
Split-view контроллеры на iPad позволяют поместить master view в левой части экрана, а правая часть содержит detail view controller и его view. Т.е. обходится без swapping-а вьюх. Поэтому контролировать перемещение данных с помощью viewWillAppear и viewWillDisappear не получится.
Когда iPad держится вертикально вверху появляется кнопка по нажатию на которую появляется pop-over с master view контроллером.
Методы setDetailItem и configureView вызываются в DetailViewController когда устанавливается новый detail item или view нуждается в обновлении.
В случае с UITableView можно использовать didSelectRowAtIndexPath.
DetailViewController содержит переменную detailItem. Её значение устанавливается в MasterViewController.m в методе didSelectRowAtIndexPath:
NSManagedObject *selectedObject =
[[self fetchedResultsController] objectAtIndexPath:indexPath];
self.detailViewController.detailItem = selectedObject;
Свойство detailItem объявлено в DetailViewController.h:
@property (strong, nonatomic) id *detailItem;
Т.к. мы точно знаем что detailItem будет класса NSManagedObject, то можно указать это явно:
@property (strong, nonatomic) NSManagedObject *detailItem;
viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.name.text = [self.detailItem valueForKey:@”name”];
}
viewWillDisappear
- (void)viewWillDisappear:(BOOL)animated
{
[self.detailItem setValue: self.name.text forKey:@”name”];
[super viewWillDisappear:animated];
}
Базовый код для сохранения в БД (помещается в viewWillDisappear):
NSError *error;
if (![self._detailObject.managedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(@”Unresolved error %@, %@”, error, [error userInfo]);
exit(-1); // Fail
}
Если вы хотите отсортировать список в master view, то это делается при создании fetchedResultsController в MasterViewController.m.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@”name” ascending:NO];
Можно еще изменить заголовок Detail в DetailViewController.m в методе initWithNibName:
if (self) {
self.title = NSLocalizedString(@”Detail”, @”Detail”);
Можно еще это сделать в setDetailItem:
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
// set the controller’s title
self.title = [self.detailItem valueForKey:@”name”];
if (self.popoverController != nil) {
[self.popoverController dismissPopoverAnimated:YES];
}
}
Split-view контроллеры на iPad позволяют поместить master view в левой части экрана, а правая часть содержит detail view controller и его view. Т.е. обходится без swapping-а вьюх. Поэтому контролировать перемещение данных с помощью viewWillAppear и viewWillDisappear не получится.
Когда iPad держится вертикально вверху появляется кнопка по нажатию на которую появляется pop-over с master view контроллером.
Методы setDetailItem и configureView вызываются в DetailViewController когда устанавливается новый detail item или view нуждается в обновлении.
В случае с UITableView можно использовать didSelectRowAtIndexPath.
DetailViewController содержит переменную detailItem. Её значение устанавливается в MasterViewController.m в методе didSelectRowAtIndexPath:
NSManagedObject *selectedObject =
[[self fetchedResultsController] objectAtIndexPath:indexPath];
self.detailViewController.detailItem = selectedObject;
Свойство detailItem объявлено в DetailViewController.h:
@property (strong, nonatomic) id *detailItem;
Т.к. мы точно знаем что detailItem будет класса NSManagedObject, то можно указать это явно:
@property (strong, nonatomic) NSManagedObject *detailItem;
viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.name.text = [self.detailItem valueForKey:@”name”];
}
viewWillDisappear
- (void)viewWillDisappear:(BOOL)animated
{
[self.detailItem setValue: self.name.text forKey:@”name”];
[super viewWillDisappear:animated];
}
Базовый код для сохранения в БД (помещается в viewWillDisappear):
NSError *error;
if (![self._detailObject.managedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(@”Unresolved error %@, %@”, error, [error userInfo]);
exit(-1); // Fail
}
Если вы хотите отсортировать список в master view, то это делается при создании fetchedResultsController в MasterViewController.m.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@”name” ascending:NO];
Можно еще изменить заголовок Detail в DetailViewController.m в методе initWithNibName:
if (self) {
self.title = NSLocalizedString(@”Detail”, @”Detail”);
Можно еще это сделать в setDetailItem:
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
// set the controller’s title
self.title = [self.detailItem valueForKey:@”name”];
if (self.popoverController != nil) {
[self.popoverController dismissPopoverAnimated:YES];
}
}