Хорошо, я понимаю ваши разочарования, потому что подавляющее большинство учебных материалов для iPhone не уделяют достаточного внимания общему дизайну приложения. Они делают все возможное для интерфейса «сладкоежка» и платят только за то, чтобы приложение обрабатывало данные , хотя обработка данных - это, в первую очередь, цель приложения!
В учебных материалах не уделяется достаточно времени объяснению шаблона проектирования Model-View-Controller, на котором основан весь API iPhone / Cocoa. Вам трудно что-либо понять, потому что вы продолжаете пытаться втиснуть функциональность в неправильные объекты из-за ошибочного убеждения, что представление пользовательского интерфейса является ядром программы, как вам подсказывают учебные материалы. В этом заблуждении ничего не имеет смысла, даже документация Apple.
Вы должны сделать шаг назад и переосмыслить. Это не функция представления, чтобы решить, какие данные отображать и когда отображать. В функции контроллера табличного представления не входит хранение, управление или хранение данных приложения. Эти функции должным образом относятся к объекту модели данных (о котором вы, возможно, никогда не слышали). У вас возникают проблемы, потому что вы пытаетесь разделить задачу модели данных по представлению и контроллеру представления, если они не принадлежат.
Очевидно, ваше приложение даже не имеет модели данных, потому что вы храните данные таблицы в качестве свойств контроллера табличного представления. Несмотря на то, что вы часто видите это в примитивных обучающих примерах, это плохой дизайн, который рухнет под сложность любого, кроме самых тривиальных приложений.
Вместо этого ваши данные должны храниться и управляться в собственном настраиваемом объекте. Это модель данных. В вашем случае это звучит так, как будто данные распределены по двум массивам, поэтому вы бы создали объект модели данных примерно так:
@interface MyDataModel : NSObject {
@protected
NSArray *arrayOne;
NSArray *arrayTwo;
@public
NSArray *currentlyUsedArray;
}
@property(nonatomic, retain) NSArray *currentlyUsedArray;
-(void) switchToArrayOne;
-(void) switchToArrayTwo;
-(void) toggleUsedArray;
@end
#import "MyDataModel.h"
@interface MyDataModel ()
@property(nonatomic, retain) NSArray *arrayOne;
@property(nonatomic, retain) NSArray *arrayTwo;
@end
@implementation MyDataModel
- (id) init{
if (self=[super init]) {
self.arrayOne=//... initialize array from some source
self.arrayTwo=//... initialize array from some source
self.currentlyUsedArray=self.arrayOne; //whatever default you want
}
return self;
}
-(void) switchToArrayOne{
self.currentlyUsedArray=self.arrayOne;
}
-(void) switchToArrayTwo{
self.currentlyUsedArray=self.arrayTwo;
}
- (void) toggleUsedArray{
if (self.currentlyUsedArray==self.arrayOne) {
self.currentlyUsedArray=self.arrayTwo;
}else {
self.currentlyUsedArray=self.arrayOne;
}
}
(Обратите внимание, что фактические данные инкапсулированы и что другие объекты могут получить доступ только к currentlyUsedArray
. Модель данных решает, какие данные предоставлять на основе внутреннего состояния данных.)
Этот объект модели данных должен находиться в общедоступном месте. Лучший способ - сделать его одноэлементным, но быстрый и грязный способ - оставить его как атрибут делегата приложения.
Итак, в вашем контроллере таблиц у вас будет свойство:
MyDataModel *theDataModel;
@property (nonatomic, retain) MyDataModel *theDataModel;
затем в реализации
@synthesize theDataModel;
-(MyDataModel *) theDataModel; {
if (theDataModel; !=nil) {
return theDataModel; ;
}
id appDelegate=[[UIApplication sharedApplication] delegate];
self.theDataModel=appDelegate.theDataModelProperty;
return theDataModel;
}
Тогда в вашем методе источника данных tableview:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...
cell.textLabel.text=[self.theDataModel.currentlyUsedArray objectAtIndex:indexPath.row];
return cell;
}
Если какое-либо событие где-либо в приложении требует, чтобы вы переключали массивы, вы просто вызываете объект модели данных из делегата приложения и отправляете ему соответствующее сообщение массива коммутатора.
id appDelegate=[[UIApplication sharedApplication] delegate];
[appDelegate.theDataModelProperty toggleUsedArray];
Теперь все последующие операции с данными, будь то в этом конкретном табличном представлении или в каком-либо другом совершенно не связанном представлении, будут использовать данные из соответствующего массива.
Зачем проходить через все эти неприятности? Это делает приложение модульным. Вы можете легко добавлять различные представления, каждое из которых отображает данные по-разному, без необходимости переписывать управление данными каждый раз. Вы можете использовать модель данных для управления данными, которые будут отображаться в таблице, в веб-представлении или в командной строке. Вы даже можете легко переместить модель данных в совершенно другое приложение.
Эта модульность значительно упрощает управление большими сложными приложениями. У вас есть только один объект, который манипулирует данными и контролирует их. Вам не нужно беспокоиться о том, что небольшая ошибка в каком-то редко используемом сегменте кода испортит все приложение. Вы можете легко добавлять представления или удалять их, не нарушая приложение.
Это, конечно, тривиальный пример, но он показывает хорошую практику.
Однако вы можете спросить, как это решает проблему представления таблицы, зная, какие данные загружать и когда их загружать? Просто, это не так. Работа табличного представления не в том, чтобы знать, какие данные загружать или когда загружать. Модель данных обрабатывает что-данные, а контроллер табличного представления обрабатывает когда. (Вы даже можете получать уведомления о проблемах модели данных, когда она обновляется, например, для URL. Тогда контроллер представления может зарегистрироваться для уведомления и вызывать reloadData
всякий раз, когда изменяется модель данных.)
Безжалостно разделяя и инкапсулируя функциональность в MVC, вы создаете сложные приложения из простых, повторно используемых компонентов, которые легко обслуживать и отлаживать.
Плохо, что большинство учебных материалов лишь на словах относятся к этой крайне критической концепции.