aumentada - nueva actualizacion de iphone
¿Cómo comparto un objeto entre UIViewControllers en iPhone? (5)
Ambos controladores de vista deben hacer referencia a un tercer objeto (C) como su fuente de datos; este objeto (C) que contiene todos los datos de aplicación almacenados.
C sería, en este caso, la M en el MVC.
Agregue a cada uno de sus ViewControllers las siguientes declaraciones:
// SomeViewController.h
// Before @interface
@class MyDataSource;
// In the interface
IBOutlet MyDataSource *datasource;
@property(retain) IBOutlet MyDataSource *datasource;
Mi aplicación es una aplicación de la barra de pestañas, con un controlador de vista separado para cada pestaña.
Tengo un objeto en mi primer controlador de vista (A) que contiene todos los datos almacenados de mi aplicación (ignore NSUserDefaults para esto) al que debo acceder el segundo controlador de vista (B) cuando presiono un botón. ¿Cómo puedo lograr esto de la mejor manera?
La forma más común que he visto esto es configurar lo que desea acceder en el delegado de la aplicación y hacer referencia a él en otros lugares como este:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
myStuff = appDelegate.stuff;
En el delegado de la aplicación, configure una variable de material y use @property y @synthesize como de costumbre.
Algunas personas dicen que no es un buen enfoque, ya que es lo mismo que usar variables globales, pero es muy común.
Me gusta crear una clase de modelo de nivel superior que sea un singleton y contenga todos los elementos que pueda necesitar.
También es útil darle un método de carga de nivel superior que rellene objetos con solo las teclas db, utilizando el patrón de hidratación / deshidratación común en los ejemplos de Apple.
El uso típico en el delegado de la aplicación sería simplemente,
[[MyModel sharedModel] load];
Y luego en un controlador de vista:
NSArray *myThing1s = [[MyModel sharedModel] thing1s];
NSArray *myThing2s = [[MyModel sharedModel] thing2s];
Luego puede iterar sobre sus thing1s y thing2s y cuando necesite detalles, simplemente puede llamar
[myThing1 hydrate];
que poblará el objeto.
Por supuesto, es probable que desee utilizar CoreData para administrar la persistencia de 3.0 en adelante.
Siempre creo un objeto especial llamado DataModel
y lo uso singleton sharedInstance
.
Y este objeto luego contiene todos los datos relacionados con la aplicación. No hay necesidad de acceder a la temida 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
Y (porque soy perezoso) puse DataModel.h
en application-prefix.pch
.
De esa manera puedo acceder a mis datos desde cualquier lugar de la aplicación simplemente llamando
[DataModel sharedModel]
Una opción que tiene es declarar su modelo de fecha como variables de instancia de su delegado de aplicación (como lo mencionaron otros comentaristas).
En lugar de hacer referencia al delegado de la aplicación como lo sugiere nevan, una alternativa es agregar una propiedad a sus clases de controlador de vista (A y B) para su modelo de datos.
Digamos que desea compartir un objeto de modelo de datos entre sus controladores de vista, puede agregar una propiedad a cada uno:
@interface AViewController : UIViewController {
MyDataModel *model;
}
@property (nonatomic, retain) MyDataModel *model;
@end
@interface BViewController : UIViewController {
MyDataModel *model;
}
@property (nonatomic, retain) MyDataModel *model;
@end
Al inicializar el controlador de vista, puede establecer esta propiedad en el contexto del objeto inicializado anteriormente.
Usted ha mencionado un controlador de barra de pestañas. Si sus controladores de vista están conectados a través de IB, todo lo que tiene que hacer es configurar estos parámetros en su método de aplicación de delegación de applicationDidFinishLaunching:
antes de que se muestre el controlador de la barra de pestañas:
@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];
}
No se olvide de lanzar el modelo en el método dealloc
su controlador de dealloc
.
La alternativa es usar un objeto singleton. Un simple ejemplo de singleton:
@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
Puede acceder a este modelo de datos desde todos los controladores de vista con algo similar a lo siguiente:
MyDataModel *model = [MyDataModel sharedDataModel];
Vea también this discusión de desbordamiento de pila sobre singletons.