Come posso condividere un object tra UIViewControllers su iPhone?

La mia applicazione è un’applicazione di tabulazioni, con un controller di visualizzazione separato per ogni scheda.

Ho un object nel mio primo controller di visualizzazione (A) che contiene tutti i miei dati dell’applicazione memorizzati (Ignora NSUserDefaults per questo) a cui è necessario accedere dal secondo controller di visualizzazione (B) quando premo un pulsante su di esso. Come posso ottenere questo nel modo migliore?

Un’opzione che devi è dichiarare il tuo modello di data come variabili di istanza del tuo delegato dell’app (come menzionato da altri commentatori).

Invece di fare riferimento al delegato dell’app come suggerito da nevan, un’alternativa è aggiungere una proprietà alle classi del controller di visualizzazione (A e B) per il modello di dati.

Supponiamo che tu voglia condividere un object modello di dati tra i tuoi controller di visualizzazione, puoi aggiungere una proprietà a ciascuno:

@interface AViewController : UIViewController { MyDataModel *model; } @property (nonatomic, retain) MyDataModel *model; @end @interface BViewController : UIViewController { MyDataModel *model; } @property (nonatomic, retain) MyDataModel *model; @end 

Quando si inizializza il controller della vista, è ansible impostare questa proprietà sul contesto dell’object inizializzato in precedenza.

Hai menzionato un controller della barra delle linguette. Se i controller della vista sono cablati tramite IB, tutto ciò che devi fare è impostare questi parametri nell’applicazione delegata applicationDidFinishLaunching: method, prima che venga visualizzato il controller della barra delle tabs:

 @interface MyAppDelegate : NSObject  { 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]; } 

Non dimenticare di rilasciare il modello nel metodo dealloc del tuo controller di dealloc .


L’alternativa è usare un object singleton. Un semplice esempio 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 

Puoi accedere a questo modello di dati da tutti i tuoi controller di visualizzazione con qualcosa di simile al seguente:

 MyDataModel *model = [MyDataModel sharedDataModel]; 

Vedi anche questa discussione sull’overflow dello stack sui singleton.

Il modo più comune che ho visto è quello di impostare la cosa a cui si desidera accedere nel delegato dell’app e fare riferimento in altri posti come questo:

 MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate]; myStuff = appDelegate.stuff; 

Nel delegato dell’app, imposta una variabile stuff e usa @property e @synthesize come al solito.

Alcuni dicono che non è un buon approccio, poiché è lo stesso che usare le variabili globali, ma è molto comune.

Mi piace creare una class Model di livello superiore che sia un singleton e contenga tutti gli elementi di cui potrei avere bisogno.

È utile anche dargli un metodo di caricamento di livello superiore che popola gli oggetti con solo i tasti db, usando il pattern idrato / disidratato comune negli esempi di Apple.

L’utilizzo tipico nel delegato dell’app sarebbe semplicemente,

 [[MyModel sharedModel] load]; 

E poi in un controller di visualizzazione:

 NSArray *myThing1s = [[MyModel sharedModel] thing1s]; NSArray *myThing2s = [[MyModel sharedModel] thing2s]; 

Puoi quindi scorrere le cose e le cose e quando hai bisogno di dettagli, puoi semplicemente chiamare

 [myThing1 hydrate]; 

che popolerà l’object.

Ovviamente, probabilmente si desidera utilizzare CoreData per gestire la persistenza dalla 3.0 in poi.

Creo sempre un object speciale chiamato DataModel e uso il suo singleton sharedInstance .

E questo object contiene quindi tutti i dati relativi alle app. Non c’è bisogno di accedere alla appDelegate .

DataModel.h

 #import  @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 

E (perché sono pigro) ho messo DataModel.h in application-prefix.pch .

In questo modo posso accedere ai miei dati da qualsiasi punto dell’applicazione semplicemente chiamando

 [DataModel sharedModel] 

Entrambi i controller di vista dovrebbero fare riferimento a un terzo object (C) come loro dataSource; questo object (C) contenente tutti i dati dell’applicazione memorizzati.

C sarebbe, in questo caso, la M nel MVC.

Aggiungi a ciascuno dei tuoi ViewControllers le seguenti dichiarazioni:

 // SomeViewController.h // Before @interface @class MyDataSource; // In the interface IBOutlet MyDataSource *datasource; @property(retain) IBOutlet MyDataSource *datasource;