2010-05-05 11 views
5

Ich habe zwei Tage lang durch einen Code geforscht, um herauszufinden, warum ich keine globale NSMutableArray-Variable abrufen konnte, die ich in der .h deklarierte und in .m implementierte und in der viewDidLoad-Funktion eingab.Wie übergeben Sie Objekte zwischen View Controllern in Objective-C?

Es dämmerte mir endlich: In Objective-C gibt es keine globale Variable, jedenfalls nicht im PHP-Sinne, den ich kenne. Ich habe die XCode Fehlerwarnungen nie wirklich gelesen, aber da war es, auch wenn nicht ganz einfach Englisch: "Instanzvariable 'blah' in der Klassenmethode angesprochen."

Meine Frage: Was soll ich jetzt tun? Ich habe zwei View-Controller, die auf ein zentrales NSMutableDictionary zugreifen müssen, das ich aus einer JSON-Datei über URL generiere. Es ist im Grunde ein erweitertes Menü für alle meine Table View-Drilldowns, und ich möchte einige andere "globale" (nicht-statische) Variablen haben.

Muss ich jedes Mal das JSON greifen, wenn ich dieses NSMutableDictionary erstellen möchte, oder gibt es eine Möglichkeit, es einmal zu setzen und von verschiedenen Klassen über #import darauf zuzugreifen? Muss ich Daten in eine Datei schreiben oder gibt es sonst eine andere Möglichkeit?

+1

"Instanzvariable 'blah' in der Klassenmethode aufgerufen."weist auf ein anderes Problem hin: Es bedeutet, dass Sie eine Klassenmethode haben (beginnend mit" + "), die versucht, auf eine Instanzvariable zu verweisen. Da Klassenmethoden per Definition nicht mit einer bestimmten Instanz der Klasse verbunden sind, t haben Zugang zu Instanzvariablen –

Antwort

9

Wenn Sie zwei View-Controller haben, die auf das freigegebene NSMutableDictionary zugreifen, können Sie einen Zeiger an übergeben das gemeinsame Wörterbuch in ihre jeweiligen Initialisierungsnachrichten?

Also in Ihrem 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]; 
} 

Und in Ihrem jeweiligen UIViewControllerOne und UIViewControllerTwo Implementierungen

- (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

Interessant! Ich wusste nicht, dass Sie eine UIViewController-Klasse mit initWithData zuweisen konnten. Ich habe an ein paar Orten gelesen, dass dies in AppDelegate ist irgendwie hackish. Ist das malarky? – buley

+0

die initWithData Nachricht ist keine Standardnachricht in UIViewController, sondern etwas, das Sie Ihren UIViewControllern hinzufügen müssen, um die Weitergabe von Daten zu übernehmen (so können Sie beliebige Parameter zu diesen Nachrichten hinzufügen.) Ich werde meine Antwort ändern, um sie zu verdeutlichen: – RedBlueThing

+0

Danke Ich bin mir sicher, dass dies die beste Antwort ist, die ich bekommen werde. Ich versuche immer noch, meinen Kopf darum zu wickeln. Hoffentlich macht es Ihnen nichts aus, wenn ich einige Nachfragen stelle, wenn sie relevant sind. – buley

1

In Obj-C gibt es globale Variablen, die Sie im App Delegate instanziieren.

Aber auf Ihr Problem möchten Sie wahrscheinlich das NSMutableDictorary übergeben, wenn Sie den neuen View-Controller wie [UIView Alloc] initWithDictionary: (NSMutableDictionary *) dict; wenn du weißt, was ich meine.

In Ihrem Beispiel haben Sie eine einzige Klasse, die eine andere Klasse anruft? Ich würde denken, dass es eine Art von Controller gibt, der bestimmt, welcher View Controller angezeigt werden soll und welches das Verzeichnis ist, auf das zugegriffen werden kann.

1

Nur eine globale Variable machen. Global bedeutet außerhalb jeden Bereichs.

NSMutableDictionary *gDictionary; 

@implementation ... 
@end 
+0

Das wäre toll, aber es scheint nicht für mich arbeiten. Ich werde es weiter versuchen. – buley

2

Es gibt in der Tat eine Reihe von Möglichkeiten, wie Sie dies tun können (ohne auf etwas Extremes wie das Schreiben in eine Datei zurückgreifen zu müssen). Sie können eine "globale" unter Verwendung erstellen:

  1. Altmodische C globale Variablen (Externen)
  2. A Singleton Klasse
  3. Instanzvariablen auf dem Application Delegate

Aber alle diese Ansätze machen Ihren View-Controller weniger modular (weil sie davon abhängen, dass sie "nach außen" gehen, um die globalen Daten zu finden). Daher ist es wahrscheinlich am besten, das Dictionary zu einer Eigenschaft der View-Controller-Klasse zu machen, die explizit vom Aufrufer gesetzt werden muss innerhalb eines initWithDictionary: m ethod oder mit einem separaten Setter).

+0

Was ist eine Singleton-Klasse? (Sorry für meine Ignoranz. Nochmal: dreckiger PHP-Coder.) – buley

+0

Ein "Singleton" ist nur ein fantastischer Name für eine Klasse, die nur einmal Instanz instanziiert (Ich werde einen Link zu meiner Antwort hinzufügen). Zum Beispiel könnten Sie eine 'MySingleton'-Klasse mit einer' sharedInstance'-Klassenmethode haben, die diese (einzelne) Instanz zurückgibt. Sie könnten dann Methoden auf der gemeinsam genutzten Instanz aufrufen: '[[MySingleton sharedInstance] setFoo: @" foo "]' –

+0

Vielen Dank, sehr klar. Danke auch für Ihren sehr hilfreichen Kommentar zu meiner ursprünglichen Frage oben. – buley

Verwandte Themen