web-dev-qa-db-fra.com

Forcer l'application iphone à redémarrer par programme

J'essaie de faire redémarrer mon application iPhone par programme lorsque le bouton Déconnexion est enfoncé.

Quelqu'un a-t-il un exemple de code à partager? J'ai lu qu'il était possible de modifier le fichier main.m mais je n'ai trouvé aucun code correspondant à cela.

Toute aide serait appréciée.

43
manospro

Tout d’abord, bien qu’il soit possible de forcer la destruction de votre application, cela n’est pas autorisé par Apple et sera rejeté. Même si elle n'a pas été rejetée, il n'y a aucun moyen de redémarrer votre application une fois qu'elle a été supprimée. Il vous suffit de trouver un moyen de réinitialiser votre application via votre code, comme le dit Jason Coco. Ce sera peut-être plus de travail, mais ça vaut le coup de ne pas se faire rejeter par Apple. 

17
sudo rm -rf

Remarque:

Bien que la réponse à cette question soit "impossible", je pense que le nouveau développeur iOS peut poser une question valide. Ils peuvent faire quelque chose qui correspond probablement à ce qu'ils souhaitent.

Il existe un moyen de "redémarrer" votre application du point de vue de l'utilisateur sans que techniquement ne redémarre ou ne quitte l'application iOS. Comme indiqué par d'autres réponses, une application iOS ne doit jamais quitter explicitement, car cela n'est pas autorisé sur iOS.

Ma réponse:

Si vous souhaitez que votre application revienne à l'état dans lequel elle se trouvait au lancement, ce n'est pas possible à 100%, mais je vais vous expliquer comment obtenir la plupart du chemin qui devrait suffire à toutes fins utiles.

La première chose à faire est de recréer votre contrôleur de vue racine. 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 suffira, mais tout état d'application que vous possédez doit également être réinitialisé avec cette méthode. Par exemple, déconnectez un utilisateur, réinitialisez tout état non persistant et annulez (libérez) 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 de application:didFinishLaunchingWithOptions.

Cours cadres et singletons:

Vous ne pourrez pas réinitialiser complètement l'état de singletons ou d'instances par application du framework, telles que celles-ci:

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

C’est probablement très bien, car vous ne devriez de toute façon pas y stocker d’état non persistant (sauf 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 un état de structure, vous pouvez le faire avec la même méthode resetAppToFirstController. Quoi qu'il en soit, il ne devrait pas être nécessaire de recréer ces objets, ni l'objet window.

Si vous avez vos propres singletons, vous pouvez les recréer en les stockant dans une classe singleton-holder (qui est elle-même un véritable singleton). Conceptuellement, il s'agit d'une simple classe singleton avec des propriétés pour chacun de vos autres singletons et une méthode reset pour les annuler et les libérer. Vos autres singletons doivent utiliser cette classe (au lieu d'une variable statique ou globale) pour stocker des instances de singleton. Soyez prudent si vous utilisez des bibliothèques tierces, car elles peuvent également utiliser des singletons et vous devrez vous assurer que celles-ci utilisent également votre détenteur d'un singleton afin de pouvoir les réinitialiser au besoin. Je pense que cette technique est de toute façon une bonne pratique, car dans certains cas (par exemple, les tests unitaires), vous souhaitez que des objets qui sont généralement des singletons s’éloignent et se réinitialisent à un état vierge. Cependant, vous ne voulez pas coupler les implémentations singleton avec votre détenteur singleton, un bon moyen de le faire est d'utiliser une variable NSMutableDictionary en tant qu'objet associé sur [UIApplication sharedApplication] avec les noms de classe singleton en tant que 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 de démarrage si vous le souhaitez comme premier contrôleur de vue.

62
jhabbott

essayez ceci, cela fonctionne 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];
}
15
roberto.buratti

Objectif c:

exit(0);

Rapide:

exit(0)

J'ai ceci sur 2 applications en direct et elles n'ont pas été rejetées. Une de mes applications a même cette ligne de code en tant que fonctionnalité dans la page d'accueil de mon application. Il est situé dans le coin supérieur droit, où le bouton Tweet est sur Twitter. Alors, ne vous inquiétez pas du rejet d’Apple, à moins que cela ne ressemble à un crash inattendu.

 enter image description here

9
Esqarrouth

Voici comment vous pouvez le faire sur simulateur en utilisant une 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 d'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.

5
Bohdan Orlov

Je quitte pendant -applicationWillResignActive: si l'application est sur l'écran de démarrage et si Apple l'accepte depuis des années. Pour l'utilisateur, cela ne ressemblera pas à un crash. La prochaine fois que l'utilisateur lance l'application à partir de l'icône. Une vérification supplémentaire qui ne quitte pas l'application si elle était lancée aujourd'hui pourrait être utile pour l'expérience utilisateur dans certains cas.

- (void)applicationWillResignActive:(UIApplication *)application
{
    // called if phone-call comes in!
    if([gameController isGameFinished])
        exit(0);
}
3
cat

Mettez ceci dans une UIAlertAction demandant à l'utilisateur "Sauvegarder et quitter". Cela animera la sortie (0), donc au moins ça a l'air prévu.

- (void)saveAndQuit
{
    [UIView animateWithDuration:0.8 animations:^{
        self.window.alpha = 0.0; // fade out...
        // ... while pinching to a point
        self.window.transform = CGAffineTransformScale(
                CGAffineTransformMakeTranslation( 0, 0 ), 0.1, 0.1 );
    } completion:^(BOOL finished) {
        exit(0);
    }];
}
0
Jeff