web-dev-qa-db-de.com

Erzwingen Sie einen programmgesteuerten Neustart der iPhone-App

Ich versuche, meine iPhone-App programmgesteuert neu zu starten, wenn die Abmelden-Taste gedrückt wird.

Hat jemand ein Codebeispiel zum Teilen? Ich habe gelesen, dass es möglich ist, die main.m-Datei zu ändern, jedoch keinen dazugehörigen Code finden konnte.

Jede Hilfe wäre dankbar.

43
manospro

Zunächst einmal ist es zwar möglich, die App zu erzwingen, aber Apple lässt dies nicht zu und wird abgelehnt. Auch wenn sie nicht abgelehnt wurde, gibt es keine Möglichkeit, die App neu zu starten, sobald sie beendet ist. Sie müssen nur einen Weg finden, um Ihre App durch Ihren Code zurückzusetzen, wie Jason Coco gesagt hat. Es könnte mehr Arbeit sein, aber es lohnt sich, nicht von Apple abgelehnt zu werden. 

17
sudo rm -rf

Anmerkung:

Obwohl dies als "nicht möglich" beantwortet wurde, denke ich, dass es eine berechtigte Frage für einen neuen iOS-Entwickler ist, und dass er etwas tun kann, was wahrscheinlich das ist, was er will.

Es gibt eine Möglichkeit, Ihre App aus Sicht des Benutzers neu zu starten, bei der nichttechnischdie iOS-App neu gestartet oder beendet wird. Wie aus anderen Antworten hervorgeht, sollte eine iOS-App niemals explizit beendet werden, da dies unter iOS nicht zulässig ist.

Meine Antwort:

Wenn Sie möchten, dass Ihre App zu dem Zustand zurückkehrt, in dem sie beim Start war, ist dies nicht zu 100% möglich, aber ich werde einen Weg erläutern, um den größten Teil des Weges dorthin zu schaffen, der für alle gültigen Zwecke ausreichen sollte.

Das erste, was Sie tun müssen, ist, Ihren Root-View-Controller neu zu erstellen. Ich empfehle dies von einer Methode im App-Delegaten aus wie folgt:

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

In vielen Fällen ist dies ausreichend, aber jeder App-Status, den Sie haben, sollte auch in dieser Methode zurückgesetzt werden. Melden Sie beispielsweise einen Benutzer ab, setzen Sie einen nicht persistenten Status zurück und machen Sie alle Objekte ungültig (geben Sie sie frei), die Sie können. Diese Methode kann auch verwendet werden, um Ihren ersten Ansichtscontroller aus application:didFinishLaunchingWithOptions zu erstellen.

Rahmenklassen und Singletons:

Sie können den Status von Framework-Singletons oder app-spezifischen Instanzen nicht vollständig zurücksetzen. Beispiel:

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

Das ist wahrscheinlich in Ordnung, da Sie in diesen sowieso keinen nicht persistenten Zustand speichern sollten (außer NSNotificationCenter, aber alle registrierten Beobachter hätten entfernt werden müssen, als die Objekte freigegeben wurden). Wenn Sie einen Framework-Status initialisieren oder zurücksetzen möchten, können Sie dies in derselben resetAppToFirstController -Methode tun. Auf jeden Fall sollte es nicht erforderlich sein, diese oder das Objekt window neu zu erstellen.

Wenn Sie über eigene Singletons verfügen, können Sie diese neu erstellen, indem Sie sie in einer Singleton-Holder-Klasse speichern (die selbst ein echter Singleton ist). Konzeptionell ist dies eine einfache Singleton-Klasse mit Eigenschaften für jede Ihrer anderen Singletons und einer reset -Methode, mit der alle ungültig gemacht und freigegeben werden können. Ihre anderen Singletons sollten diese Klasse (anstelle einer statischen oder globalen Variablen) zum Speichern von Singleton-Instanzen verwenden. Seien Sie vorsichtig, wenn Sie Bibliotheken von Drittanbietern verwenden, da diese möglicherweise auch Singletons verwenden, und Sie müssen sicherstellen, dass diese auch Ihren Singleton-Holder verwenden, damit Sie sie bei Bedarf zurücksetzen können. Ich halte diese Technik sowieso für eine gute Praxis, da in einigen Fällen (z. B. beim Testen von Einheiten) Objekte, bei denen es sich in der Regel um Singletons handelt, ausgeblendet und in einen ursprünglichen Zustand zurückversetzt werden sollen. Sie möchten die Singleton-Implementierungen jedoch nicht mit Ihrem Singleton-Inhaber koppeln. Eine gute Möglichkeit, dies zu implementieren, ist die Verwendung von NSMutableDictionary als zugehöriges Objekt in [UIApplication sharedApplication] mit den Singleton-Klassennamen als Schlüssel. Ich gehe jedoch etwas vom Thema ab, da dies eine fortgeschrittenere Technik ist, die über den Rahmen dieser Frage hinausgeht.


Das oben Genannte sollte ausreichen, um Ihre Anwendung für den Benutzer zurückzusetzen. Sie können den Begrüßungsbildschirm sogar erneut anzeigen, wenn Sie als erste Ansichtssteuerung möchten.

65
jhabbott

probieren Sie das aus, es funktioniert für mich.

-(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

Ziel c:

exit(0);

Schnell:

exit(0)

Ich habe dies auf 2 Live-Apps, und diese wurden nicht abgelehnt. Eine meiner Apps enthält sogar diese Codezeile als Funktion auf der Startseite meiner App. Es befindet sich in der oberen rechten Ecke, wo der Tweet-Button auf Twitter ist. Machen Sie sich also keine Sorgen, dass Apple ablehnt, es sei denn, es sieht nach einem unerwarteten Absturz aus.

 enter image description here

9
Esqarrouth

So können Sie dies auf einem Simulator mit privater API tun:

    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);

Dies sollte auch für jailbroken-Apps mit entsprechenden Berechtigungen funktionieren.

Für andere Apps kann eine einfache HTML-Seite verwendet werden:

    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);

Leider wird in diesem Fall eine Internetverbindung benötigt.

5
Bohdan Orlov

Ich beende während -applicationWillResignActive: wenn sich die App auf dem Startbildschirm befindet und Apple sie seit Jahren akzeptiert. Für den Benutzer wird es nicht wie ein Absturz aussehen. Nächstes Mal startet der Benutzer die App über das Symbol. Eine zusätzliche Prüfung, die die App nicht beendet, wenn sie heute gestartet wurde, kann in einigen Fällen für die Benutzererfahrung nützlich sein.

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

Fügen Sie dies in eine UIAlertAction ein, die den Benutzer "Save and Quit" fragt. Es wird den Ausgang animieren (0), so dass es zumindest geplant aussieht.

- (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