2009-03-15 4 views
1

Ich versuche, einen Multiview-Controller für ein Spiel zu erstellen, in dem ein Root View Controller Ansichten freigibt, bevor er zu einer anderen Ansicht wechselt. Die Sub-View-Controller sind wiederum Sub-Root-View-Controller selbst, da sie andere View-Controller enthalten.Wie können Ansichten im Multiview-Controller ordnungsgemäß freigegeben und umgeschaltet werden?

Zum Beispiel wird mein singlePlayerViewController einen ShakeObjectViewController und möglicherweise andere haben. Wenn Sie zwischen den Ansichten Aktionssets verwenden und mit dem Anwendungsdelegaten als Delegat des Aktionsblatts arbeiten, funktioniert alles wie erwartet, wenn Sie von einer Einzelspieleransicht zu einer anderen wechseln.

Aber wenn ich versuche, einen neuen singlePlayerViewController mit den gleichen Init-Methoden zu erstellen, wirft der Debugger eine EXC _BAD _ACCESS Fehler, wenn ich versuche, eine Unteransicht einfügen, nämlich shakeObjectViewController.view.

Initialisierung sieht wie folgt aus im Moment: Die AppDelegate das Fenster mit der Methode Standard init initialisiert,

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    // Override point for customization after application launch 
    [window addSubview:rootViewController.view]; 
    [window makeKeyAndVisible]; 
} 

dann in der RootViewController.m der viewDidLoad,

if(singlePlayerViewController == nil) { 

     SinglePlayerViewController *singleController = [[SinglePlayerViewController alloc] 
             initWithNibName:@"SinglePlayerView" bundle:nil]; 
     self.singlePlayerViewController = singleController; 
     [singleController release]; 
    } 

    [self.view insertSubview:singlePlayerViewController.view atIndex:0]; 

Gefolgt von singlePlayerViewController .m,

- (void)viewDidLoad { 
    self.view.tag = kSinglePlayerView; // tag the view 

    ShakeObjectViewController *shakeController = [[ShakeObjectViewController alloc] 
             initWithNibName:@"ShakeObjectView" bundle:nil]; 
    self.shakeObjectViewController = shakeController; 
    self.view = shakeController.view; 
    [shakeController release]; 
} 

Beachten Sie, dass mein singlePlayerViewController keine Unteransichten einfügt, sondern stattdessen seine eigene Ansicht durch die Ansicht eines Unteransicht-Controllers ersetzt. (Sie wissen nicht, ob dies eine gute Praxis ist oder nicht:?:)

Wenn Ansichten wechseln, die AppDelegate führt die folgenden Schritte aus:

for(UIView *subview in [rootViewController.view subviews]) 
{ 
    [subview removeFromSuperview]; 
} 
[rootViewController.singlePlayerViewController release] 

[rootViewController initMultiplayerView]; 

Wenn dann zurück zum Einzelspieler-Modus schalten, die gleiche Die init-Methode in der viewDidLoad von rootViewController.m wird ausgeführt, und der Debugger löst den Fehler auf dem "[self.view insertSubview: singlePlayerViewController.view atIndex: 0];" Linie.

Irgendwelche Ideen, warum eine neue Ansicht nicht erstellt wird? Ich habe versucht, den singlePlayerViewController auf Null zu setzen, anstatt zu veröffentlichen, aber dann wird der Fehler auf die "self.view = shakeController.view;" Linie. Es war mein Verständnis, dass, wenn die Ansichtseigenschaft derzeit Null ist, automatisch eine neue für Sie beim nächsten Zugriff auf die Ansicht erstellt wird.

Ist initWithNibName nur für die einmalige Ausführung gedacht? Oder ist mein Design in Bezug auf # View-Controller viel zu kompliziert?

Antwort

2

Beachten Sie, dass mein singlePlayerViewController keine Subviews einfügt, sondern stattdessen seine eigene Ansicht durch die Ansicht eines Subview-Controllers ersetzt. (Weiß nicht ob das eine gute Übung ist oder nicht:?:)

Riesige Warnflagge hier. Es klingt, als ob Sie eine Ansicht mit zwei View-Controllern haben. Das ist schlecht.

Betrachten Einfügen und Entfernen Subviews statt:

  • RootView
    • SinglePlayerView (mit MutliplayerView entfernt und ersetzt werden)
      • ShakeView

Auf diese Weise haben Sie 3 Ansichten mit 3 View-Controllern.

Es ist die Art, wie das Framework verwendet werden sollte.

0

Ihr Design scheint ein wenig übermäßig komplex, aber das bedeutet nicht, dass der Debugger zufällige Fehler werfen sollte! :) Der Versuch, es zu vereinfachen, könnte jedoch helfen. Ich sehe nicht, warum Sie eine Single-Player-Ansicht wünschen, wenn Sie sie sofort durch eine Shake-Objektansicht ersetzen.

Ich denke definitiv, dass Sie singlePlayerViewController auf Null setzen wollen, weil sonst die Zeile "if (singlePlayerViewController == nil) {" in rootViewControllers viewDidLoad Methode falsch ist, und ein neuer View-Controller wird nicht gemacht, was ist warum bekommst du diesen ersten Fehler?

Ich sehe nur 3 Möglichkeiten, wie Sie einen Zugriffsfehler auf der Linie bekommen können „self.view = shakeController.view“:

  • shakeController ist nicht null, aber Müll.Dies scheint unwahrscheinlich, da es nur init'ed ist, es sei denn, seine ViewDidLoad selbst oder ähnliches veröffentlicht.
  • Selbst ist nicht Null, aber Müll. Wieder ist es unwahrscheinlich, aber möglich - vielleicht checken Sie den Debugger ein, um zu sehen, wie das selbe aussieht (machen ihre Variablen Sinn, etc.)
  • Wenn Sie self.view = ... aufrufen, wird eine Freigabe an das Original gesendet Aussicht. Gibt es einen Code in der Dealloc-Methode der Einzelspieler-Ansicht, der einen Zugriffsfehler verursachen könnte?

, die entweder selbst oder shakeController sein nil würde einen Fehler nicht verursachen, weil die Linie zu

entspricht
[self setView:[shakeController view]] 

, die nicht abstürzen würde, wenn jene Null waren, da Nachrichten auf Null erlaubt sind.

+0

Die Singleplayer-Ansicht wechselt möglicherweise zwischen anderen Ansichten, nicht nur die Shake-Ansicht. Es wurde versucht, die Zeile "if (singlePlayerViewController == nil)" zu kommentieren und trotzdem einen neuen Controller zu instanziieren. Derselbe Fehler. "NSLog (@" shake's view =% @ ", shakeController.view);", wirft den gleichen Fehler. – oohaba

+0

Es wurde auch versucht, den Controller des Einzelspieler-Views komplett zu überspringen und shakeObject VC direkt im Root-Controller zu verwenden. Derselbe Fehler. Switching BTW Ansichten funktioniert gut, wenn ich nicht versuche, sie zu veröffentlichen, aber ich brauche jedes Mal eine neue Ansicht. danke für die Antwort. – oohaba

+0

Sind alle Ihre @property-Anweisungen mit "retain" gekennzeichnet? –

0

Yup, alle @property-Anweisungen markiert mit (nichtatomare, behalten).

Vielleicht kann die Frage neu formuliert werden, wie erstellen Sie einen View-Controller aus einer Feder mehr als einmal? Beim zweiten Mal, wenn ich eine VC erstelle, unabhängig davon, ob ich eine vorherige VC derselben Klasse freigebe, wird die zugehörige Ansicht nicht erstellt und wirft den Fehler BAD ACCESS auf.

0

Die Art, wie Sie dies getan haben, ist sehr verwirrend für mich, und ich denke, ist verantwortlich für Ihren Fehler. Ich gehe Zeile für Zeile durch und versuche herauszufinden, warum es abstürzt und es nicht ganz herauszufinden, aber gleichzeitig fällt es mir schwer herauszufinden, was mit den Ansichten während des Switch passiert.

Ich würde dies neu schreiben, wie Kailoa mit drei verschiedenen View-Controllern vorschlägt. Jede Ansicht sollte einen eigenen Controller haben. Eine Ansicht sollte sich nicht selbst ersetzen, sie sollte durch ihren Superview-Controller ersetzt werden.

Ich vermute, dass irgendwo in ihr etwas losgelassen wird und dann Nachricht, und dann versuchen Sie etwas mit der Rückkehr dieser Nachricht zu tun, denken, dass etwas ein Objekt ist, wenn es nicht ist.

Verwandte Themen