Appeler une méthode de AppDelegate - Objective-C
J'ai essayé d'appeler une méthode existante de mon ViewController.m
de AppDelegate.m
à l'intérieur de la applicationDidEnterBackground
méthode, donc j'ai trouvé ce lien: L'appel de UIViewController méthode à partir de l'app délégué, qui m'a dit de mettre en œuvre ce code:
Dans mon ViewController.m
-(void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;
}
Dans mon AppDelegate:
@class MyViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (weak, nonatomic) MyViewController *myViewController;
@end
Et dans l'AppDelegate mise en œuvre:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.myViewController method];
}
Alors j'ai mis ce code dans mon projet et il a bien fonctionné, mais je n'ai pas compris comment fonctionne le code, ligne par ligne. Ce qui ne l' sharedApplication
faire? Pourquoi dois-je d'un délégué au lieu de simplement la création d'une instance de ViewController, comme:
ViewController * instance = [[ViewController alloc] init];
[instance method];
OriginalL'auteur lucas_turci | 2014-05-03
Vous devez vous connecter pour publier un commentaire.
Informations d'arrière-plan (définition de la classe vs instance de classe)
Le concept le plus important ici est la différence entre la définition d'une classe et une instance de classe.
La définition de la classe est le code source de la classe. Par exemple
ViewController.m
contient la définition de lamyViewController
classe, etAppDelegate.m
contient la définition de laAppDelegate
classe. L'autre catégorie mentionnée dans votre question estUIApplication
. C'est un système de classe définie, c'est à dire que vous n'avez pas le code source de cette classe.Un instance de classe est un morceau de la mémoire sur le tas, et un pointeur vers la mémoire. Une instance de classe est généralement créé avec une ligne de code comme ceci
Noter que
alloc
réserve de l'espace sur le tas pour la classe, et puisinit
définit les valeurs initiales pour les variables/propriétés de la classe. Un pointeur vers l'instance est enregistrée dansfoo
.Au démarrage de votre application, la séquence suivante d'événements se produit (en gros):
la variable système
delegate
dans le UIApplication instanceLe stockage du pointeur MyViewController est là que les choses deviennent confuses. L'AppDelegate classe a un UIWindow propriété appelée
window
. (Vous pouvez voir que dans AppDelegate.h). Si l'application dispose d'une seule vue-contrôleur, puis le pointeur vers cette vue-contrôleur est stocké dans lewindow.rootViewController
de la propriété. Mais si l'application dispose de plusieurs contrôleurs de vue (en vertu d'un UINavigationController ou un UITabBarController) puis les choses se compliquent.Le code spaghetti solution
De sorte que le problème que vous rencontrez, c'est que lorsque le système appelle le
applicationDidEnterBackground
méthode, comment voulez-vous obtenir le pointeur de la vue-contrôleur? Eh bien, techniquement, le délégué d'application est un pointeur vers la vue-contrôleur quelque part dans lewindow
de la propriété, mais il n'y a pas de moyen facile d'obtenir que le pointeur (en supposant que l'application a plus d'une vue contrôleur).L'autre thread a proposé un code spaghetti approche du problème. (Notez que le code spaghetti approche a été suggéré que parce que l'OP dans l'autre thread n'a pas à faire les choses correctement, avec des notifications.) Voici comment le code spaghetti œuvres
Ce code récupère le pointeur de la UIApplication exemple que le système mis en place, puis interroge le
delegate
propriété pour obtenir un pointeur vers l'AppDelegate instance. Le pointeur deself
, qui est un pointeur vers la MyViewController exemple, est ensuite stockée dans une propriété dans le AppDelegate.Le pointeur de la MyViewController instance peut ensuite être utilisé lorsque le système appelle
applicationDidEnterBackground
.La bonne solution
La bonne solution est d'utiliser les notifications (comme dans kkumpavat réponse)
Avec les notifications, vous n'êtes pas un stockage redondant des pointeurs vers votre point de vue contrôleurs, et vous n'avez pas à comprendre où le système a enregistré le pointeur de votre vue-contrôleur. En appelant
addObserver
pour laUIApplicationDidEnterBackgroundNotification
vous dites que le système d'appel de la vue du contrôleur dedidEnterBackground
méthode directement.OriginalL'auteur user3386109
Vous avez deux question ici.
1) Quelle est l'
sharedApplication
faire?Le
[UIApplication sharedApplication]
vous donne UIApplication instance appartient à votre demande. C'est centralisée point de contrôle pour vous App. Pour plus d'informations, vous pouvez lire UIApplication de référence de classe sur iOS développeur de site de.2) Pourquoi dois-je d'un délégué au lieu de simplement la création d'une instance de ViewController?
La création de contrôleur dans
AppDelegate
nouveau à l'aide dealloc
/init
va créer une nouvelle instance et cette nouvelle instance ne pointe pas vers le contrôleur, vous faites allusion. Donc, vous n'obtiendrez pas le résultat que vous recherchez.Toutefois, dans ce cas d'utilisation particulier de
applicationDidEnterBackground
, vous n'avez pas besoin d'avoir la référence du contrôleur de vous enAppDelegate
. Vous ViewController pouvez vous inscrire pourUIApplicationDidEnterBackgroundNotification
notification dansviewDidLoad
fonction et annuler l'inscription dansdealloc
fonction.OriginalL'auteur kkumpavat
La-vue-contrôleur est déjà instancié dans le cadre de la PLUME/storyboard du processus, de sorte que si votre application délégué ne dispose de son propre
alloc
/init
, vous êtes tout simplement la création d'une autre instance (qui n'a aucun rapport avec celui créé la PLUME/storyboard).Le but de la construction que vous décrivez est simplement de l'application de déléguer une référence à la vue contrôleur de la PLUME/storyboard instancié pour vous.
OriginalL'auteur Rob