Как я могу совместно использовать объект между UIViewControllers на iPhone?
Мое приложение - это приложение панели вкладок с отдельным контроллером представления для каждой вкладки.
У меня есть объект в моем первом контроллере представления (A), который содержит все мои данные хранимых приложений (просьба игнорировать NSUserDefaults для этого), к которым должен быть обращен второй контроллер представления (B), когда я нажимаю на него кнопку. Как я могу достичь этого наилучшим образом?
Ответы
Ответ 1
Один из вариантов заключается в том, чтобы объявить вашу модель даты в качестве переменных экземпляра вашего делегата приложения (как упоминалось другими комментаторами).
Вместо ссылки на делегат приложения, предложенный nevan, альтернативой является добавление свойства к вашим классам контроллера представления (A и B) для вашей модели данных.
Предположим, вы хотите поделиться объектом модели данных между контроллерами представлений, которые вы можете добавить к каждому из них:
@interface AViewController : UIViewController {
MyDataModel *model;
}
@property (nonatomic, retain) MyDataModel *model;
@end
@interface BViewController : UIViewController {
MyDataModel *model;
}
@property (nonatomic, retain) MyDataModel *model;
@end
Когда вы инициализируете свой контроллер представлений, вы можете установить это свойство в контексте объекта, инициализированном ранее.
Вы упомянули контроллер панели вкладок. Если ваши контроллеры просмотра подключены через IB, все, что вам нужно сделать, это установить эти параметры в своем делетететом делегирования applicationDidFinishLaunching:
, прежде чем отобразится контроллер панели вкладок:
@interface MyAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
{
MyDataModel *model;
AViewController *aViewController;
BViewController *bViewController;
...
}
@property (retain) IBOutlet AViewController *aViewController;
@property (retain) IBOutlet BViewController *aViewController;
@end
@implementation MyAppDelegate
...
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
...
aViewController.model = model;
bViewController.model = model;
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
Не забудьте выпустить модель в вашем контроллере вида dealloc
.
Альтернативой является использование одноэлементного объекта. Простой пример синглтона:
@interface MyDataModel : NSObject
{
}
+ (MyDataModel *) sharedDataModel;
@end
@implementation MyDataModel
static MyDataModel *sharedDataModel = nil;
+ (MyDataModel *) sharedDataModel
{
@synchronized(self)
{
if (sharedDataModel == nil)
{
sharedDataModel = [[MyDataModel alloc] init];
}
}
return sharedDataModel;
}
@end
Вы можете получить доступ к этой модели данных со всех контроллеров вашего вида с помощью примерно следующего:
MyDataModel *model = [MyDataModel sharedDataModel];
См. также
Ответ 2
Самый распространенный способ, которым я это видел, - настроить то, что вы хотите получить в делегате приложения, и ссылаться на него в других местах:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
myStuff = appDelegate.stuff;
В делегате приложения настройте переменную stuff и используйте как обычно, @property и @synthesize.
Некоторые люди говорят, что это не очень хороший подход, поскольку он аналогичен использованию глобальных переменных, но он очень распространен.
Ответ 3
Мне нравится создавать класс модели верхнего уровня, который является одноэлементным и содержит все элементы, которые могут мне понадобиться.
Полезно также дать ему метод загрузки верхнего уровня, который заполняет объекты только с помощью клавиш db, используя шаблон гидрата/дегидрата, распространенный в примерах Apple.
Типичное использование в делегате приложения было бы просто,
[[MyModel sharedModel] load];
И затем в контроллере вида:
NSArray *myThing1s = [[MyModel sharedModel] thing1s];
NSArray *myThing2s = [[MyModel sharedModel] thing2s];
Затем вы можете перебирать свои вещи и вещи2, а когда вам нужны детали, вы можете просто позвонить
[myThing1 hydrate];
который заполнит объект.
Конечно, вы, вероятно, захотите использовать CoreData для управления персистентностью начиная с 3.0.
Ответ 4
Я всегда создаю специальный объект с именем DataModel
и использую его singleton sharedInstance
.
И этот объект затем содержит все связанные с приложением данные. Нет необходимости в доступе к страшному appDelegate
.
DataModel.h
#import <Foundation/Foundation.h>
@class MyClass1, MyClass2;
@interface DataModel : NSObject
@property (copy, nonatomic) NSString *aString;
@property (assign) BOOL aBool;
@property (strong) MyClass1 *myObject1;
@property (strong) MyClass2 *myObject2;
+ (DataModel *)sharedModel;
@end
DataModel.m
#import "DataModel.h"
#import "Class1.h"
#import "Class2.h"
@implementation DataModel
- (id) init
{
self = [super init];
if (self)
{
_myObject1 = [[MyClass1 alloc] init];
_myObject2 = [[MyClass2 alloc] init];
aBool = NO;
aString = nil;
}
return self;
}
+ (DataModel *)sharedModel
{
static DataModel *_sharedModel = nil;
static dispatch_once_t onceSecurePredicate;
dispatch_once(&onceSecurePredicate,^
{
_sharedModel = [[self alloc] init];
});
return _sharedModel;
}
@end
И (потому что я ленив) я положил DataModel.h
в application-prefix.pch
.
Таким образом, я могу получить доступ к своим данным из любого места приложения, просто позвонив
[DataModel sharedModel]
Ответ 5
Оба контроллера представления должны ссылаться на третий объект (C) как на свой источник данных; этот объект (C) содержит все сохраненные данные приложения.
C будет в этом случае M в MVC.
Добавьте к каждому из ваших ViewControllers следующие объявления:
// SomeViewController.h
// Before @interface
@class MyDataSource;
// In the interface
IBOutlet MyDataSource *datasource;
@property(retain) IBOutlet MyDataSource *datasource;