ViewControllers zerstören nicht

8

Ich habe ein ernstes Problem mit meiner iOS App.

Ich habe eine Login-Logik in meiner Anwendung. Beim Anmelden und Abmelden zerstören einige View-Controller nicht. Dies verursacht einige Probleme, zum Beispiel einige Ereignisse, die ich mit NSNotifcationCenter emittiere, werden einige Male ausgegeben. Diese Probleme sind vermeidbar, aber ich möchte wirklich eine Lösung, um zu vermeiden, dass einige View-Controller im Hintergrund offen bleiben, ohne dass ich sie kontrolliere.

Die Steuerung der Login-Logik erfolgt folgendermaßen:

Wenn in der Startfunktion des Anwendungsdelegaten der Benutzer bereits angemeldet ist, setze ich den Stammansicht-Controller auf den Haupt-View-Controller. Daher mache ich nichts, und der Root-View-Controller wird über das Storyboard auf den Navigationscontroller des Login-View-Controllers gesetzt.

Wenn der Benutzer sich abmeldet, benutze ich einen modalen Übergang, um den View-Controller zurück zum Navigationscontroller des Login-View-Controllers zu bringen.

Wie Sie vielleicht verstehen, verwende ich Storyboards, Swift und das neueste iOS.

Mein Abmeldecode ist ein Übergang, der mich zum LoginViewControler führt:

%Vor%

Mein App-Stellvertretercode:

%Vor%

Was mache ich falsch?

Ich würde mich über Hilfe freuen:)

BEARBEITEN

Ich habe sogar versucht, den Root-View-Controller in die Logout-Aktion zu setzen, und das hat auch nicht geholfen. Wie ist das überhaupt möglich?

So mache ich jetzt die Abmeldung:

%Vor%     
gal 28.05.2016, 14:40
quelle

10 Antworten

2

Egal, wie Sie Ihre Übertragungen verwalten, vergessen Sie nicht, den Beobachter hinzuzufügen oder zu entfernen, wenn der Ansichtscontroller apear / disappear ist.

    
Nevgauker 29.05.2016 17:39
quelle
1

Wenn der Bildschirm angemeldet den Bildschirm Anmeldung anzeigt und der Bildschirm Anmeldung den Bildschirm angemeldet anzeigt Sie werden einen Zyklus haben, der sich auf neue View-Controller anhäuft. Um das zu lösen, muss man nicht das andere präsentieren, sondern sich darauf entspannen. Eine andere Möglichkeit besteht darin, Instanzen von jedem als Singletons zu halten und diese nur darzustellen.

    
Adam H. 28.05.2016 14:58
quelle
1

Adam H. hat Recht. Wenn dies nicht funktioniert, prüfen Sie, ob IBOutlets und Delegaten mit starken Beziehungen vorhanden sind, und ändern Sie sie in schwache Beziehungen. d. h.

%Vor%

Ohne das Schlüsselwort weak wird der View-Controller niemals entfernt.

Je nachdem, wie Ihr Projekt eingerichtet ist, würden Sie, wenn Sie einen Navigationscontroller verwenden (den ich empfehle), jedes Mal, wenn sich jemand abmeldet,

eingeben %Vor%

Damit wird alles vom Navigations-Stack entfernt, der alle View-Controller enthält (es sei denn, Sie haben starke Beziehungen, dann werden sie nicht entfernt)

    
SeanRobinson159 28.05.2016 15:01
quelle
1

Ich habe so etwas vor nicht allzu langer Zeit implementiert und mir scheint, dass Sie den Lebenszyklus von UINavigationController missbrauchen. Nachdem ich Ihre Frage zweimal gelesen habe, scheint es, als ob Sie Ihren Login-View-Controller als UINavigationController initialisieren, der View-Controller stapelt. Sobald sich der Benutzer abmeldet, behalten Sie den Stack und fügen dem Stack mit dem performSegue weitere ViewControllers hinzu. Sie können es vermeiden, indem Sie zwei verschiedene Szenen verwenden - 1) Login View Controller, der selbstständig steht. 2) Hauptfluss Ihrer App - kann mit UITabController / UINavigationController starten, beides oder was auch immer.

In AppDelegate überprüfen Sie - Wenn der Benutzer angemeldet ist, führen Sie Ihre Logiken aus und setzen Sie die App rootVC auf den Hauptfluss vc. Andernfalls setzen Sie den loginVC (UIViewController) als Root.

Damit können Sie die Login-VC auch bei Bedarf im Hauptfluss frei machen, ohne den Hauptfluss zu beeinträchtigen. In Ihrem Fall ist der loginVC immer der Root-Bereich von UINavigationController, so dass Sie PopToRootVC jedes Mal, wenn Sie ihn sehen wollen, ausführen oder ausführen wollen, was noch schlimmer ist, weil Sie dann eine andere Instanz eines UINavigationControllers erstellen und Ressourcen nicht freigegeben werden.

Offensichtlich gibt es in der Programmierung in den meisten Fällen viele Lösungen für ein Problem. Ich bin mir sicher, dass dein Problem mit deinem Flow gelöst werden kann. Ich denke nur, es ist eine schlechte Erfahrung, ein loginVC über einen Navigationscontroller zu stapeln.

    
devdc 02.06.2016 23:25
quelle
1

Ein Teil des Problems besteht darin, dass das Setzen eines neuen rootViewController auf UIWindow die Ansichtshierarchie nicht vom alten Root-View-Controller entfernt. Dadurch bleiben alle Arten von starken Referenzen übrig, und wenn Sie das Xcode-Debugging verwenden, können Sie sehen, dass die alte Ansichtshierarchie immer noch dort sitzt, hinter der neuen Sichthierarchie von rootViewController .

So etwas sollte das Problem für Sie beheben und Ihren View-Controllern die Deinstallation ermöglichen:

%Vor%     
Daniel Hall 03.06.2016 00:05
quelle
1

entfernen Sie die ARC-Datei nach Datei in Build-Einstellungen oder Großhandel pro Projekt (es scheint, dass Sie nicht-ARC-Projekt haben können, aber schwache Referenzen haben während es dabei ist: nicht sportlich, nehme ich an, aber du kannst beides haben.)

Überschreiben Sie dann Retain und Release im problematischen View-Controller und sehen Sie, wer die zusätzliche Referenz hält, indem Sie die Überschreibung einleiten behalten und freigeben. Es sollte eine pädagogische Erfahrung sein.

Der faule Ansatz besteht darin, ARC nur für die fragliche VC zu töten.

Ich wäre gespannt, wie das bei VCs funktioniert, die in swift geschrieben sind; -)

Ich denke, es ist ein weiterer Grund, noch länger im objc-Domizil zu bleiben bis / ob swift Compiler und Runtime erstarrt (wenn überhaupt).

Hoffe das hilft jedem.

PS: Es dauert ewig, um eine schnelle Datei in meinem Projekt zu kompilieren, und ich habe NEIN Idee, welche schnelle Datei das verursacht. Duh.

    
Anton Tropashko 06.06.2016 14:15
quelle
1

Wie bereits erwähnt, gibt es nicht viele Informationen, um die Lösung für Ihre Frage richtig zu liefern. Ich kann Ihnen vorschlagen, Ihren Ansatz zu ändern. Ich habe einen ähnlichen Workflow mit einem UINavigationController (navigationController) von AppDelegate gestartet, innerhalb von wenn ich angemeldet bin, legte ich als ViewControllers:

( self ist navigationController und rootViewController ist ein weiteres UINavigationController )

%Vor%

Wenn Sie nicht angemeldet sind, fügen Sie nur loginViewController ein:

%Vor%

In diesem Fall können Sie rootViewController angeben, wo der Benutzer angemeldet ist. Das ist mein 2cent.

    
ciccioska 09.06.2016 21:31
quelle
1

Ich mag eine Root-VC , die einfach leer ist. Wenn die App gestartet wird, zeigt root VC sofort login VC als untergeordnete VC von root VC an. Wenn der Benutzer sich erfolgreich authentifiziert, benachrichtigt der Login-VC den Root-VC, der dann main VC als untergeordnetes Root-VC hinzufügt, übergänge von Login-VC zu (mit einer netten Animation) Haupt-VC (mit [self transitionFromViewController: toViewController: duration: options: animations: completion:] ), und entfernt dann Login-VC als Kind und verwirft es. Beim Abmelden benachrichtigt Haupt-VC den Root-VC, der dann dasselbe in umgekehrter Reihenfolge tut. Die meiste Zeit haben Sie also entweder Login VC oder Main VC instanziiert; das einzige Mal, dass sie beide instanziiert werden, ist während des Übergangs.

Ich finde, dass Segmente nützlich sind, um schnelle Prototypen zu erstellen, aber für Produktions-Apps bevorzuge ich es, sie nicht zu verwenden.

    
Brett Donald 10.06.2016 04:31
quelle
1

Ich denke, der ViewControllers Stack von euch wird so gehen: - Erster Start: LoginVC - Nach dem Login: LoginVC - TabarVC - Klicken Sie auf Abmelden: LoginVC - TabarVC - LoginVC ....

Ihr folgender Code sollte also funktionieren:

%Vor%

Aber es ist nicht :(. Meiner Meinung nach sollten Sie immer den tabarVC rootViewController. Und TabarVC einchecken, wenn Benutzer nicht eingeloggt oder Benutzer gedrückte Abmeldung, Present loginVC und verwerfen Sie es statt performSegue.

    
Son Le 10.06.2016 09:27
quelle
0

Sie müssen Ihre:

entfernen %Vor%

Stattdessen können Sie diese Methode segue überschreiben, das ist genug:

%Vor%

Über dein NSNotification gibt es zwei Methoden, um es zu entfernen:

%Vor%

In Swift können Sie die removeObservers in die neue und spezielle deinit Methode .

    
Alessandro Ornano 06.06.2016 09:05
quelle

Tags und Links