51 votes

Forcer l'application iphone à redémarrer de manière programmatique ?

J'essaie de faire en sorte que mon application iPhone redémarre de manière programmatique lorsque le bouton de déconnexion est pressé.

Quelqu'un a-t-il un exemple de code à partager ? J'ai lu que c'était possible en modifiant le fichier main.m mais je n'ai pas trouvé de code à ce sujet.

Toute aide serait appréciée.

0 votes

12 votes

Vous ne pouvez pas vraiment le forcer à redémarrer. Vous pouvez le forcer à mourir, mais vous serez probablement rejeté pour cela. Vous devriez plutôt concevoir votre application de manière à pouvoir effacer par programme toutes les données et les réinitialiser vous-même.

0 votes

Tant que le crash est initié par l'utilisateur, il ne devrait pas être rejeté. Par exemple, une application bancaire peut avertir l'utilisateur que quelque chose n'est pas synchronisé, ou qu'un délai trop long s'est écoulé depuis la dernière activation, et qu'il devra se reconnecter, et lui proposer un bouton "quitter maintenant" (comme seul choix). Ce n'est pas un problème car l'utilisateur s'attend à ce que cela se produise. Je ne dis pas que c'est la meilleure ou la seule façon de réinitialiser/se déconnecter, mais c'est acceptable, en ce qui concerne Apple, la dernière fois que j'ai vérifié.

66voto

jhabbott Points 6191

Note :

Bien qu'il ait été répondu que ce n'était pas possible, je pense que c'est une question valable pour un nouveau développeur iOS et il y a quelque chose qu'il peut faire, ce qui est probablement ce qu'il veut.

Il existe un moyen de redémarrer votre application du point de vue de l'utilisateur qui n'est pas techniquement redémarrer ou quitter l'application iOS. Comme indiqué dans d'autres réponses, une application iOS ne devrait jamais se terminer explicitement, car cela n'est pas autorisé sur iOS.

Ma réponse :

Si vous voulez que votre application revienne à l'état dans lequel elle était au lancement, ce n'est pas possible à 100%, mais je vais vous expliquer une façon d'y parvenir qui devrait suffire à toutes fins utiles.

La première chose à faire est de recréer votre contrôleur de vue Root. Je recommande de le faire à partir d'une méthode dans le délégué de l'application comme ceci :

- (void)resetAppToFirstController
{
    self.window.rootViewController = [[MyMainViewController alloc] initWithNibName:nil bundle:nil];
}

Dans de nombreux cas, cela sera suffisant, mais tout état d'application que vous avez doit également être réinitialisé par cette méthode. Par exemple, déconnectez un utilisateur, réinitialisez tout état non persistant et annulez (relâchez) tous les objets que vous pouvez. Cette méthode peut également être utilisée pour créer initialement votre premier contrôleur de vue à partir des éléments suivants application:didFinishLaunchingWithOptions .

Classes du cadre et singletons :

Vous ne serez pas en mesure de réinitialiser complètement l'état des singletons du framework ou des instances per-app, telles que celles-ci :

[UIApplication sharedApplication];
[NSNotificationCenter defaultCenter];
[NSUserDefaults standardUserDefaults];
[UIScreen screens];
// etc...

C'est probablement bien, car vous ne devriez pas y stocker d'état non persistant de toute façon (à l'exception de NSNotificationCenter mais tous les observateurs enregistrés devraient avoir été supprimés lorsque les objets ont été libérés). Si vous souhaitez initialiser ou réinitialiser l'état du framework, vous pouvez le faire dans la même procédure que celle utilisée pour l'initialisation. resetAppToFirstController méthode. Quoi qu'il en soit, il ne devrait pas y avoir besoin de recréer ces éléments, ou la méthode window objet.

Si vous avez vos propres singletons, vous pouvez les recréer en les stockant dans une classe porteuse de singleton (qui est elle-même un vrai singleton). Conceptuellement, il s'agit d'une simple classe singleton avec des propriétés pour chacun de vos autres singletons et une propriété reset pour les annuler et les libérer tous. Vos autres singletons doivent utiliser cette classe (au lieu d'une variable statique ou globale) pour stocker les instances de singletons. Faites attention si vous utilisez des bibliothèques tierces, car elles peuvent également utiliser des singletons et vous devrez vous assurer qu'elles utilisent également votre porte-singletons afin de pouvoir les réinitialiser si nécessaire. Je pense que cette technique est une bonne pratique de toute façon, parce que dans certains cas (par exemple les tests unitaires) vous voulez que les objets qui sont habituellement des singletons s'en aillent et se réinitialisent à un état immaculé. Cependant, vous ne voulez pas coupler les implémentations des singletons avec votre porte-singletons, donc une bonne façon d'implémenter ceci est d'utiliser un objet de type NSMutableDictionary comme objet associé sur [UIApplication sharedApplication] avec les noms des classes singleton comme clés. Cependant, je m'éloigne un peu du sujet car il s'agit d'une technique plus avancée qui dépasse le cadre de cette question.


Ce qui précède devrait suffire à "réinitialiser" votre application en ce qui concerne l'utilisateur. Vous pouvez même afficher à nouveau l'écran d'accueil si vous le souhaitez en tant que premier contrôleur de vue.

20voto

sudo rm -rf Points 19115

Tout d'abord, bien qu'il soit possible de forcer l'arrêt de votre application, cela n'est pas autorisé par Apple et sera rejeté. Même si cela n'était pas rejeté, il n'y a aucun moyen de redémarrer votre application une fois qu'elle a été tuée. Vous devez juste trouver un moyen de réinitialiser votre application à travers votre code, comme Jason Coco a dit. C'est peut-être plus de travail, mais ça vaut la peine de ne pas être rejeté par Apple.

0 votes

26 votes

Suite au commentaire ci-dessus, qui a été prématurément coupé : "Ne quittez jamais une application iOS de manière programmatique car les gens ont tendance à interpréter cela comme un crash. Cependant, si des circonstances externes empêchent votre application de fonctionner comme prévu, vous devez informer vos utilisateurs de la situation et leur expliquer ce qu'ils peuvent faire." Donc ne quittez pas votre utilisateur de manière inattendue, mais si c'est une action initiée par l'utilisateur, avec une explication, alors Apple n'a aucun problème avec cela. Nous utilisons exit(0) dans 4 applications approuvées.

15voto

roberto.buratti Points 1058

Essayez ceci, ça marche pour moi.

-(void)restart
{
    MyAppDelegate *appDelegate = (MyAppDelegate *)([UIApplication sharedApplication].delegate);
    [appDelegate.navigationController popToRootViewControllerAnimated:NO];
    UIViewController *topViewController = appDelegate.navigationController.topViewController;
    Class class = [topViewController class];
    NSString *nibName = topViewController.nibName;
    UIViewController *rootViewcontroller = (UIViewController *)([[class alloc] initWithNibName:nibName bundle:nil]);
    [appDelegate.navigationController.view removeFromSuperview];
    appDelegate.navigationController.viewControllers = [NSArray arrayWithObject:rootViewcontroller];
    [appDelegate.window addSubview:appDelegate.navigationController.view];
    [appDelegate.window makeKeyAndVisible];
}

2 votes

Oui je sais, l'idée est de mettre l'application dans un état qui est aussi proche que possible de l'état "initial"... Cette astuce fonctionne bien UNIQUEMENT si votre application est basée sur un contrôleur de navigation mais l'idée est facilement applicable à d'autres situations.

8voto

Esq Points 498

Objective-C :

exit(0);

Swift :

exit(0)

Je l'ai fait sur 2 applications en direct et elles n'ont pas été rejetées. Une de mes applications a même cette ligne de code comme une fonctionnalité dans la page d'accueil de mon application. Elle est située dans le coin supérieur droit, là où se trouve le bouton "tweet" de Twitter. Ne vous inquiétez donc pas du rejet par Apple, sauf si cela ressemble à un crash inattendu.

enter image description here

5voto

Bohdan Orlov Points 46

Voici comment vous pouvez le faire sur le simulateur en utilisant l'API privée :

    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@", scheme, endpointString]];

    Class pClass = NSClassFromString(@"BKSSystemService");
    id service = [[pClass alloc] init];

    SEL pSelector = NSSelectorFromString(@"openURL:application:options:clientPort:withResult:");
    NSMethodSignature *signature = [service methodSignatureForSelector:pSelector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.target = service;
    NSString *app = @"com.apple.mobilesafari";
    [invocation setSelector:pSelector];
    [invocation setArgument:&URL atIndex:2];
    [invocation setArgument:&app atIndex:3];
    unsigned int i = [service performSelector:NSSelectorFromString(@"createClientPort")];
    [invocation setArgument:&i atIndex:5];
    [invocation invoke];
    exit(0);

Cela devrait également fonctionner sur les applications jailbreakées avec les droits appropriés.

Pour les autres applications, une simple page html peut être utilisée :

    NSString *format = @"https://dl.dropboxusercontent.com/s/rawt1ov4nbqh4yd/launchApp.html?scheme=%@&URL=%@";
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:format, scheme, endpointString]];
    [[UIApplication sharedApplication] openURL:URL];
    exit(0);

Malheureusement, une connexion Internet est nécessaire dans ce cas.

0 votes

C'est une vue intéressante sur les internes. Bien sûr, il utilise l'API privée d'Apple qui serait rejetée de l'AppStore. Je l'ai upvoted parce que j'avais besoin d'une solution uniquement à des fins de test. Malheureusement votre premier code ne fonctionne plus sur iOS 9 (peut-être que la signature de la méthode a changé ) - il fonctionne avec le simulateur iOS 8.4. Le 2ème code fonctionne sur n'importe quel simulateur, mais il est un peu délicat de trouver ce que le code HTML doit faire

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X