Hintergrundinformationen (Klassendefinition vs Klasseninstanz)
Das wichtige Konzept hier ist 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 auf dem Heap und ein Zeiger auf diesen Speicher. Eine Instanz der Klasse wird in der Regel mit einer Codezeile wie dieser
myClass *foo = [[myClass alloc] init];
Hinweis erstellt, dass alloc
reserviert Platz auf dem Heap für die Klasse, und dann init
die Anfangswerte für die Variablen/Eigenschaften der Klasse setzt. Ein Zeiger auf die Instanz wird dann in foo
gespeichert.
Wenn die Anwendung gestartet wird, tritt die folgende Sequenz von Ereignissen (grob gesprochen):
- das System
- der Zeiger auf die UIApplication Instanz eine Instanz der UIApplication Klasse erstellt irgendwo in einem gespeichert Systemvariable
- das System erstellt eine Instanz der Klasse AppDelegate
- der Zeiger auf den AppDelegate in einer variablen namens gespeichert
delegate
in der UIApplication Instanz
- erzeugt das System eine Instanz der Klasse MyViewController
- der Zeiger auf die MyViewController Klasse irgendwo gespeichert
Die Speicherung des Zeigers auf MyViewController ist, wo die Dinge chaotisch. Die AppDelegate-Klasse verfügt über eine UIWindow-Eigenschaft mit dem Namen 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 Eigenschaft window.rootViewController
gespeichert. Aber wenn die App mehrere View-Controller hat (unter einem UINavigationController oder einem UITabBarController), wird es kompliziert.
Die Spaghetti-Code-Lösung
So ist die Frage, die Sie stellen, ist dies: wenn das System die applicationDidEnterBackground
Methode aufruft, wie Sie den Zeiger auf den View-Controller bekommen? 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 bekommen (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 der OP in dem anderen Thread wollte nicht mit Benachrichtigungen Dinge richtig tun.) Hier ist, wie der Spaghetti-Code
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;
Dieser Code funktioniert ruft den Zeiger auf den UIApplication Instanz, die das System erstellt hat, und fragt dann die delegate
-Eigenschaft ab, um einen Zeiger auf die AppDelegate-Instanz zu erhalten. Der Zeiger auf self
, der ein Zeiger auf die MyViewController-Instanz ist, wird dann in einer Eigenschaft in dem 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, Benachrichtigungen zu verwenden (wie in der Antwort des kkumpavat)
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)didEnterBackground
{
NSLog(@"Entering background now");
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Mit Benachrichtigungen, Sie nicht redundanten Zeiger auf Ihre Ansicht-Controller speichern, und Sie Sie müssen nicht herausfinden, wo das System den Zeiger auf Ihren View-Controller gespeichert hat. Wenn Sie addObserver
für die UIApplicationDidEnterBackgroundNotification
aufrufen, sagen Sie dem System, dass es die didEnterBackground
Methode des View Controllers direkt aufrufen soll.
Vielen Dank! Sehr vollständige Antwort! –