2010-05-05 19 views
5

Sto scorrendo un po 'di codice per due giorni cercando di capire perché non è stato possibile recuperare una variabile globale NSMutableArray che ho dichiarato in .h e implementata in .m e impostata in una funzione viewDidLoad.Come si passano gli oggetti tra i controller di vista in Objective-C?

Finalmente mi sono reso conto: non esiste una variabile globale in Objective-C, almeno non nel senso PHP che ho imparato a conoscere. Non ho mai letto veramente gli avvertimenti sugli errori di XCode, ma eccolo lì, anche se non del tutto semplice: "Variabile di istanza 'blah' acceduta nel metodo di classe."

La mia domanda: cosa dovrei fare ora? Ho due controller di vista che devono accedere a un NSMutableDictionary centrale generato da un file JSON tramite URL. È fondamentalmente un menu esteso per tutti i drill down di Table View e mi piacerebbe avere un paio di altre variabili "globali" (non statiche).

Devo prendere il JSON ogni volta che voglio generare questo NSMutableDictionary o c'è un modo per impostarlo una volta e accedervi da varie classi tramite #import? Devo scrivere i dati su un file o c'è un altro modo in cui le persone lo fanno di solito?

+1

"Variabile di istanza" blah "a cui si accede nel metodo di classe."indica un problema diverso: significa che hai un metodo di classe (che inizia con" + ") che sta tentando di fare riferimento a una variabile di istanza. Poiché i metodi di classe sono, per definizione, non connessi a nessuna particolare istanza della classe, essi non t avere accesso alle variabili di istanza –

risposta

9

Se si hanno due controller di vista che accedono al NSMutableDictionary condiviso, si può passare un puntatore a il dizionario comune nei rispettivi messaggi di init?

Quindi nel tuo AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    // the app delegate doesn't keep a reference this, it just passes it to the 
    // view controllers who retain the data (and it goes away when both have been released) 
    NSMutableDictionary * commonData = [[NSMutableDictionary new] autorelease]; 

    // some method to parse the JSON and build the dictionary 
    [self populateDataFromJSON:commonData]; 

    // each view controller retains the pointer to NSMutableDictionary (and releases it on dealloc) 
    self.m_viewControllerOne = [[[UIViewControllerOne alloc] initWithData:commonData] autorelease]; 
    self.m_viewControllerTwo = [[[UIViewControllerTwo alloc] initWithData:commonData] autorelease]; 
} 

E nei vostri rispettivi UIViewControllerOne e UIViewControllerTwo implementazioni

- (id)initWithData:(NSMutableDictionary*)data 
{ 
    // call the base class ini 
    if (!(self=[super init])) 
     return nil; 

    // set your retained property 
    self.sharedData = data; 
} 

// don't forget to release the property 
- (void)dealloc { 
    [sharedData release]; 
    [super dealloc]; 
} 
+0

Interessante! Non sapevo che potessi allocare una classe UIViewController con initWithData Ho letto in un paio di casi che fare questo in AppDelegate è un po 'hacker.È quel maligno? – buley

+0

il messaggio initWithData non è un messaggio standard in UIViewController, è qualcosa che dovrai aggiungere ai tuoi UIViewControllers per gestire il trasferimento dei dati (in modo da poter aggiungere qualunque parametro ti piaccia a questi messaggi) .Rifarrò la mia risposta per chiarire. – RedBlueThing

+0

Grazie Sono abbastanza sicuro che questa sia la risposta migliore che otterrò, ma cercherò ancora di approfondire la questione, spero che non ti dispiaccia se chiedo alcune domande di follow-up se sono rilevanti – buley

1

Ci sono variabili globali in Obj-C, le istanziate nel Delegato app.

Ma sul problema probabilmente si desidera passare NSMutableDictonary quando si crea un'istanza del nuovo controller di visualizzazione come [Divieta UIView] initWithDictionary: (NSMutableDictionary *) dict; se capisci cosa intendo.

Nel tuo esempio hai una singola classe che chiama un'altra classe? Penserei che ci sia una sorta di controller che determina quale controller visualizzare e che sarebbe il posto per accedere e passare il dizionario

1

Basta fare una variabile globale. Global significa al di fuori di ogni ambito.

NSMutableDictionary *gDictionary; 

@implementation ... 
@end 
+0

Sarebbe fantastico ma non sembra funzionare per me. Continuerò a provare. – buley

2

Non ci sono, infatti, un sacco di modi si può fare questo (senza ricorrere a qualcosa di estremo come scrivere su un file). È possibile creare un "globale" utilizzando:

  1. variabili Vecchio stile C globali (gli esterni)
  2. A Singleton classe
  3. variabili di istanza sulla delegato Application

Ma tutti questi gli approcci rendono il controller di visualizzazione meno modulare (perché dipendono dal raggiungere "esterno" per trovare i dati globali), quindi l'approccio migliore è probabilmente rendere il dizionario una proprietà della classe controller di visualizzazione che deve essere esplicitamente impostata dal chiamante (all'interno di initWithDictionary: m ethod, o con un setter separato).

+0

Cos'è una classe singleton? (Scusa per la mia ignoranza. Ancora: codificatore PHP sporco.) – buley

+0

Un "Singleton" è solo un nome di fantasia per una classe che crea un'istanza solo una volta (aggiungo un collegamento alla mia risposta). Ad esempio potresti avere una classe 'MySingleton' con un metodo di classe' sharedInstance' che restituisce quell'istanza (singola). È quindi possibile chiamare metodi sull'istanza condivisa come: '[[MySingleton sharedInstance] setFoo: @" foo "]' –

+0

Grazie, molto chiaro. Inoltre, grazie per il tuo commento molto utile sulla mia domanda iniziale qui sopra. – buley

Problemi correlati