Rufen Sie eine Methode von AppDelegate - Objective-C

8

Ich habe versucht, eine existierende Methode von ViewController.m von AppDelegate.m in der Methode applicationDidEnterBackground aufzurufen, also habe ich diesen Link gefunden: Aufruf der UIViewController-Methode vom App-Delegaten , die mir die Implementierung dieses Codes befahl:

In meinem ViewController.m

%Vor%

In meinem AppDelegate:

%Vor%

Und in der AppDelegate-Implementierung:

%Vor%

Also habe ich diesen Code in mein Projekt eingefügt und es hat gut funktioniert, aber ich habe nicht verstanden, wie der Code Zeile für Zeile funktioniert. Was macht die sharedApplication ? Warum muss ich einen Delegaten setzen, anstatt nur eine Instanz von ViewController zu erstellen, wie zum Beispiel:

%Vor%     
lucas_turci 03.05.2014, 13:10
quelle

3 Antworten

16

Hintergrundinformationen (Klassendefinition gegen Klasseninstanz)

Das wichtige Konzept ist hier der Unterschied zwischen einer Klassendefinition und einer Klasseninstanz.

Die Klassendefinition ist der Quellcode für die Klasse. Zum Beispiel enthält ViewController.m die Definition für die Klasse myViewController und AppDelegate.m enthält die Definition für die Klasse AppDelegate . Die andere in Ihrer Frage erwähnte Klasse ist UIApplication . Das ist eine systemdefinierte Klasse, d. H. Sie haben keinen Quellcode für diese Klasse.

Eine Klasseninstanz ist ein Stück Speicher im Heap und ein Zeiger auf diesen Speicher. Eine Klasseninstanz wird normalerweise mit einer Codezeile wie dieser erstellt.

%Vor%

Beachten Sie, dass alloc Speicherplatz auf dem Heap für die Klasse reserviert und dann init die Anfangswerte für die Variablen / Eigenschaften der Klasse festlegt. Ein Zeiger auf die Instanz wird dann in foo gespeichert.

Wenn Ihre Anwendung startet, tritt die folgende Sequenz von Ereignissen auf (grob gesprochen):

  • Das System erstellt eine Instanz der UIApplication-Klasse
  • Der Zeiger auf die UIApplication-Instanz wird irgendwo in a gespeichert Systemvariable
  • Das System erstellt eine Instanz der AppDelegate-Klasse
  • Der Zeiger auf das AppDelegate wird in einer Variablen namens delegate in der UIApplication-Instanz
  • Das System erstellt eine Instanz der MyViewController-Klasse
  • Der Zeiger auf die MyViewController-Klasse ist irgendwo gespeichert

Die Speicherung des Zeigers auf MyViewController ist, wo Dinge unordentlich werden. Die AppDelegate-Klasse verfügt über eine UIWindow-Eigenschaft namens window . (Sie können dies in AppDelegate.h sehen.) Wenn die App nur über einen Ansichtscontroller verfügt, wird der Zeiger auf diesen Ansichtscontroller in der window.rootViewController -Eigenschaft gespeichert. Aber wenn die App mehrere View-Controller hat (unter einem UINavigationController oder einem UITabBarController), werden die Dinge kompliziert.

Die Spaghetti-Code-Lösung

Das Problem, auf das Sie stoßen, ist folgendes: Wenn das System die Methode applicationDidEnterBackground aufruft, wie erhalten Sie den Zeiger auf den View-Controller? Nun, technisch gesehen hat der App-Delegate einen Zeiger auf den View-Controller irgendwo unter der window -Eigenschaft, aber es gibt keine einfache Möglichkeit, diesen Zeiger zu erhalten (vorausgesetzt, die App hat mehr als einen View-Controller).

Der andere Thread schlug einen Spaghettikode-Ansatz für das Problem vor. (Beachten Sie, dass der Spaghetti-Code-Ansatz nur vorgeschlagen wurde, weil das OP in diesem anderen Thread die Dinge nicht korrekt mit Benachrichtigungen erledigen wollte.) So funktioniert der Spaghetti-Code

%Vor%

Dieser Code ruft den Zeiger auf die vom System erstellte UIApplication-Instanz ab und fragt dann die Eigenschaft delegate ab, um einen Zeiger auf die AppDelegate-Instanz abzurufen. Der Zeiger auf self , der ein Zeiger auf die MyViewController-Instanz ist, wird dann in einer Eigenschaft in AppDelegate gespeichert.

Der Zeiger auf die MyViewController-Instanz kann dann verwendet werden, wenn das System applicationDidEnterBackground aufruft.

Die richtige Lösung

Die richtige Lösung ist die Verwendung von Benachrichtigungen (wie in kkumpavats Antwort)

%Vor%

Mit Benachrichtigungen speichern Sie keine überflüssigen Zeiger auf Ihre View-Controller, und Sie müssen nicht herausfinden, wo das System den Zeiger auf Ihren View-Controller gespeichert hat. Wenn Sie addObserver für UIApplicationDidEnterBackgroundNotification aufrufen, weisen Sie das System an, die Methode didEnterBackground des View-Controllers direkt aufzurufen.

    
user3386109 03.05.2014, 15:51
quelle
6

Sie haben zwei Fragen hier.

1) Was macht die sharedApplication ?
Die [UIApplication sharedApplication] gibt Ihnen die UIApplication-Instanz gehört zu Ihrer Anwendung. Dies ist der zentrale Kontrollpunkt für Ihre App. Weitere Informationen finden Sie UIApplication-Klassenreferenz auf iOS-Entwicklern Website.

2) Warum muss ich einen Delegaten setzen, anstatt nur eine Instanz von ViewController zu erstellen?
Wenn Sie den Controller in AppDelegate erneut mit alloc / init erstellen, wird eine neue Instanz erstellt, und diese neue Instanz zeigt nicht auf den Controller, auf den Sie verweisen. So erhalten Sie nicht das Ergebnis, das Sie suchen.
In diesem speziellen Anwendungsfall von applicationDidEnterBackground benötigen Sie jedoch keine Referenz Ihres Controllers in AppDelegate . Ihr ViewController kann sich für UIApplicationDidEnterBackgroundNotification notification in viewDidLoad function registrieren und in dealloc function die Registrierung aufheben.

%Vor%     
kkumpavat 03.05.2014 14:17
quelle
4

Der View-Controller ist bereits als Teil des NIB- / Storyboard-Prozesses instanziiert. Wenn also Ihr App-Delegat sein eigenes alloc / init erstellt, erstellen Sie einfach eine weitere Instanz (die keine Beziehung zu der erstellten erstellt) NIB / Storyboard).

Der Zweck des Konstrukts, das Sie skizzieren, besteht lediglich darin, dem App-Delegierten einen Verweis auf den View-Controller zu geben, den das NIB / Storyboard für Sie instanziiert hat.

    
Rob 03.05.2014 13:20
quelle