wake-up-neo.com

Richtige Möglichkeit zum Beenden der iPhone-Anwendung?

Ich programmiere eine iPhone-App und muss sie aufgrund bestimmter Benutzeraktionen beenden. Welche Methode ist nach dem Aufräumen des von der App zugewiesenen Speichers zum Beenden der Anwendung geeignet?

266
user21293

Haben Sie exit(0) ausprobiert?

Alternative, [[NSThread mainThread] exit], obwohl ich nicht ausprobiert habe, dass es wie die passendere Lösung scheint.

214
Brett

Auf dem iPhone gibt es kein Konzept zum Beenden einer App. Die einzige Aktion, die zum Beenden einer App führen kann, ist das Berühren der Home-Taste auf dem Telefon. Entwickler haben keinen Zugriff darauf.

Laut Apple sollte Ihre App nicht von alleine terminieren. Da der Benutzer nicht auf die Schaltfläche "Home" geklickt hat, vermittelt jede Rückkehr zum Startbildschirm den Eindruck, dass Ihre App abgestürzt ist. Dies ist ein verwirrendes, nicht standardmäßiges Verhalten und sollte vermieden werden.

271
August

exit (0) erscheint einem Benutzer als Absturz. Zeigen Sie dem Benutzer daher eine Bestätigungsmeldung an. Nach der Bestätigung pausieren (Home-Taste programmgesteuert drücken) und 2 Sekunden warten, während die App im Hintergrund mit Animation läuft, dann die Ansicht des Benutzers verlassen

-(IBAction)doExit
{
    //show confirmation message to user
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Confirmation"
                                                 message:@"Do you want to exit?"
                                                delegate:self
                                       cancelButtonTitle:@"Cancel"
                                       otherButtonTitles:@"OK", nil];
    [alert show];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != 0)  // 0 == the cancel button
    {
        //home button press programmatically
        UIApplication *app = [UIApplication sharedApplication];
        [app performSelector:@selector(suspend)];

        //wait 2 seconds while app is going background
        [NSThread sleepForTimeInterval:2.0];

        //exit app when app is in background
        exit(0);
    }
}
48
Salim

Es ist nicht wirklich eine Möglichkeit, das Programm zu beenden, sondern eine Möglichkeit, Leute zum Beenden zu zwingen.

UIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:@"Hit Home Button to Exit" message:@"Tell em why they're quiting" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[anAlert show];
39
cwe7976

Überprüfen Sie die Fragen und Antworten hier: https://developer.Apple.com/library/content/qa/qa1561/_index.html

F: Wie kann ich meine iOS-Anwendung programmgesteuert beenden?

Es gibt keine API zum ordnungsgemäßen Beenden einer iOS-Anwendung.

In iOS drückt der Benutzer die Home-Taste, um Anwendungen zu schließen. Sollte Ihre Anwendung unter Bedingungen arbeiten, unter denen sie ihre beabsichtigte Funktion nicht bereitstellen kann, wird empfohlen, dem Benutzer eine Warnung anzuzeigen, die die Art des Problems und mögliche Maßnahmen angibt, die der Benutzer ergreifen könnte - Aktivieren von WLAN, Aktivieren von Ortungsdiensten usw. Ermöglichen Sie dem Benutzer, die Anwendung nach eigenem Ermessen zu beenden.

WARNUNG: Rufen Sie nicht die Funktion exit auf. Anwendungen, die exit aufrufen, scheinen für den Benutzer abgestürzt zu sein, statt eine ordnungsgemäße Beendigung durchzuführen und zum Startbildschirm zurückzukehren.

Darüber hinaus werden Daten möglicherweise nicht gespeichert, da -applicationWillTerminate: und ähnliche UIApplicationDelegate Methoden werden nicht aufgerufen, wenn Sie exit aufrufen.

Wenn es während der Entwicklung oder des Testens erforderlich ist, Ihre Anwendung zu beenden, wird die Funktion abort oder das Makro assert empfohlen

39
Wagh

Gehen Sie zu Ihrer info.plist und überprüfen Sie den Schlüssel "Anwendung läuft nicht im Hintergrund". Dieses Mal, wenn der Benutzer auf die Home-Schaltfläche klickt, wird die Anwendung vollständig beendet.

38
Kalyan

Fügen Sie die Eigenschaft UIApplicationExitsOnSuspend für application-info.plist Zu true hinzu.

17
Aman Agarwal

Nach einigen Tests kann ich Folgendes sagen:

  • verwenden der privaten Schnittstelle: [UIApplication sharedApplication] führt dazu, dass die App wie abgestürzt aussieht, ABER es wird - (void)applicationWillTerminate:(UIApplication *)application aufgerufen, bevor dies ausgeführt wird.
  • wenn Sie exit(0); verwenden, wird die Anwendung ebenfalls beendet, sie sieht jedoch "normal" aus (die Symbole des Sprungbretts sehen wie erwartet aus, mit dem Effekt "Verkleinern"), ABER die Delegierungsmethode - (void)applicationWillTerminate:(UIApplication *)application wird nicht aufgerufen .

Mein Rat:

  1. Rufen Sie das - (void)applicationWillTerminate:(UIApplication *)application auf dem Delegat manuell auf.
  2. Rufen Sie exit(0); auf.
13
rchampourlier

Ihr ApplicationDelegate wird vom Benutzer über das absichtliche Beenden informiert:

- (void)applicationWillResignActive:(UIApplication *)application {

Wenn ich diese Benachrichtigung erhalte, rufe ich einfach an

        exit(0);

Welches macht die ganze Arbeit. Und das Beste ist, es ist die Absicht des Benutzers zu beenden, weshalb dies kein Problem sein sollte, es dort aufzurufen.

In meiner Audio-App musste die App beendet werden, nachdem die Benutzer ihr Gerät synchronisiert hatten, während die Musik noch abgespielt wurde. Sobald die Synchronisierung abgeschlossen ist, erhalte ich eine Benachrichtigung. Aber das Beenden der App direkt danach würde tatsächlich wie ein Absturz aussehen.

Deshalb setze ich stattdessen ein Flag, um die App bei der nächsten Hintergrundaktion WIRKLICH zu beenden. Welches ist in Ordnung, um die App nach einer Synchronisierung zu aktualisieren.

8
L'g

Meine App wurde kürzlich abgelehnt, da ich eine undokumentierte Methode verwendet habe. Buchstäblich:

"Leider kann es nicht zum App Store hinzugefügt werden, da es eine private API verwendet. Die Verwendung von nicht öffentlichen APIs, wie im Abschnitt 3.3.1 der Lizenzvereinbarung für das iPhone-Entwicklerprogramm beschrieben, ist untersagt:

"3.3.1 Anwendungen dürfen nur dokumentierte APIs in der von Apple) vorgeschriebenen Weise verwenden und dürfen keine privaten APIs verwenden oder aufrufen."

Die nicht öffentliche API, die in Ihrer Anwendung enthalten ist, lautet terminateWithSuccess. "

6
user223106

Apple sagt:

"Warnung: Rufen Sie die Exit-Funktion nicht auf. Anwendungen, die Exit aufrufen, scheinen abgestürzt zu sein, anstatt eine ordnungsgemäße Beendigung durchzuführen und zum Startbildschirm zurückzukehren."

Ich halte das für eine schlechte Annahme. Wenn der Benutzer auf eine Schaltfläche zum Beenden tippt und eine Meldung angezeigt wird, die etwa lautet: "Die Anwendung wird jetzt beendet.", Scheint sie nicht abgestürzt zu sein. Apple sollte eine gültige Möglichkeit zum Beenden einer Anwendung bieten (nicht zum Beenden von (0)).

6
AGPX

Dies hat eine gute Antwort bekommen, aber beschlossen, ein wenig zu erweitern:

Sie können Ihre Anwendung nicht in AppStore aufnehmen, ohne die iOS-Richtlinien für Benutzeroberflächen von Apple sorgfältig gelesen zu haben. (Sie behalten sich das Recht vor, Sie abzulehnen, wenn Sie etwas gegen sie unternehmen .) Der Abschnitt "Programmatisch nicht beenden" http: // developer .Apple.com/library/ios/# DOKUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html ist eine genaue Richtlinie, wie Sie in diesem Fall vorgehen sollten.

Wenn Sie jemals ein Problem mit der Apple Plattform haben, für das Sie nicht leicht eine Lösung finden können, wenden Sie sich an HIG. Es ist möglich Apple möchte dies einfach nicht tun es und sie normalerweise (ich bin nicht Apple, also kann ich nicht immer garantieren) sagen dies in ihrer Dokumentation.

4
nanonyme

Wir können die App nicht mit den Funktionen exit(0), abort() beenden, da Apple von der Verwendung dieser Funktionen dringend abgeraten wird. Sie können diese Funktionen jedoch zu Entwicklungs- oder Testzwecken verwenden.

Wenn es während der Entwicklung oder des Testens erforderlich ist, Ihre Anwendung zu beenden, wird die Abbruchfunktion oder das Assert-Makro empfohlen

Finden Sie diesen Apple Q & A Thread, um weitere Informationen zu erhalten.

Bei Verwendung dieser Funktion entsteht ein Eindruck, als würde die Anwendung abstürzen. Ich habe also einen Vorschlag bekommen, wie wir einen Alarm mit einer Beendigungsnachricht anzeigen können, um den Benutzer auf das Schließen der App aufmerksam zu machen, da bestimmte Funktionen nicht verfügbar sind.

Aber iOS Human Interface Guideline für Starten und Stoppen der App , was darauf hindeutet, dass Niemals die Schaltfläche Beenden oder Schließen zum Beenden der Anwendung verwendet wird. Stattdessen schlagen sie vor, die richtige Meldung anzuzeigen, um die Situation zu erklären.

Eine iOS-App zeigt niemals die Option Schließen oder Beenden an. Benutzer beenden die Verwendung einer App, wenn sie zu einer anderen App wechseln, zum Startbildschirm zurückkehren oder ihre Geräte in den Energiesparmodus versetzen.

Beenden Sie eine iOS-App niemals programmgesteuert. Die Leute neigen dazu, dies als Absturz zu interpretieren. Wenn etwas Ihre App daran hindert, wie beabsichtigt zu funktionieren, müssen Sie die Benutzer über die Situation informieren und erklären, was sie dagegen tun können.

3
technerd

Zusätzlich zu dem oben Gesagten, gute Antwort, die ich nur hinzufügen wollte, denke darüber nach, dein Gedächtnis aufzuräumen.

Nach dem Beenden Ihrer Anwendung bereinigt das iPhone OS automatisch alle von Ihrer Anwendung zurückgebliebenen Daten. Wenn Sie also den gesamten Speicher manuell freigeben, kann dies die Zeit verlängern, die Ihre Anwendung zum Beenden benötigt.

2
Chris Jefferson

Hm, Sie müssen die Anwendung möglicherweise "beenden", wenn Ihre Anwendung beispielsweise eine Internetverbindung erfordert. Sie könnten eine Warnung anzeigen und dann so etwas tun:

if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
    [[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
    kill(getpid(), SIGINT); 
}
2
Rob
- (IBAction)logOutButton:(id)sender
{
   //show confirmation message to user
   CustomAlert* alert = [[CustomAlert alloc] initWithTitle:@"Confirmation" message:@"Do you want  to exit?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
   alert.style = AlertStyleWhite;
   [alert setFontName:@"Helvetica" fontColor:[UIColor blackColor] fontShadowColor:[UIColor clearColor]];
   [alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

   if (buttonIndex != 0)  // 0 == the cancel button
   {
      //home button press programmatically
      UIApplication *app = [UIApplication sharedApplication];
      [app performSelector:@selector(suspend)];
      //wait 2 seconds while app is going background
      [NSThread sleepForTimeInterval:2.0];
      //exit app when app is in background
      NSLog(@"exit(0)");
      exit(0);
  }
}
2

Ich habe den oben erwähnten [[NSMutableArray new] addObject: nil] -Ansatz verwendet, um das Beenden (Abstürzen) der App zu erzwingen, ohne einen Funktionsaufruf zum Verlassen der Funktion (0) durchzuführen.

Warum? Da meine App das Anheften von Zertifikaten für alle Netzwerk-API-Aufrufe verwendet, um Man-in-the-Middle-Angriffe zu verhindern. Dazu gehören die Initialisierungsaufrufe, die meine Finanz-App beim Start durchführt.

Wenn die Zertifikatauthentifizierung fehlschlägt, werden bei allen meinen Initialisierungsaufrufen Fehler ausgegeben, und meine App befindet sich in einem unbestimmten Zustand. Es hilft nicht, den Benutzer nach Hause und dann zurück in die App zu lassen, da die App, sofern sie nicht vom Betriebssystem gelöscht wurde, immer noch nicht initialisiert und nicht vertrauenswürdig ist.

In diesem Fall halten wir es für das Beste, eine Warnung zu senden, die den Benutzer darüber informiert, dass die App in einer unsicheren Umgebung ausgeführt wird, und dann, wenn er auf "Schließen" klickt, das Beenden der App mit der oben beschriebenen Methode zu erzwingen.

1
Michael Long
[[UIApplication sharedApplication] terminateWithSuccess];

Es hat gut funktioniert und ruft automatisch an

- (void)applicationWillTerminateUIApplication *)application delegate.

fügen Sie diesen Code hinzu, um die Warnung zur Kompilierungszeit zu entfernen

@interface UIApplication(MyExtras)
  - (void)terminateWithSuccess;
@end 
1
shiva

Sie sollten die Funktion exit(0) nicht direkt aufrufen, da sie die Anwendung sofort beendet und aussieht, als wäre Ihre App abgestürzt. Zeigen Sie den Benutzern daher besser einen Bestätigungsalarm und lassen Sie sie dies selbst tun.

Swift 4.2

func askForQuit(_ completion:@escaping (_ canQuit: Bool) -> Void) {
    let alert = UIAlertController(title: "Confirmation!", message: "Do you want to quit the application", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { (action) in
        alert.dismiss(animated: true, completion: nil)
        completion(true)
    }))
    alert.addAction(UIAlertAction(title: "No", style: UIAlertAction.Style.cancel, handler: { (action) in
        alert.dismiss(animated: true, completion: nil)
        completion(false)
    }))
    self.present(alert, animated: true, completion: nil)
}

/// Will quit the application with animation
func quit() {
    UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
    /// Sleep for a while to let the app goes in background
    sleep(2)
    exit(0)
}

Verwendungszweck:

self.askForQuit { (canQuit) in
     if canQuit {
         self.quit()
     }
}
0
TheTiger

Der Benutzer sollte entscheiden, wann eine App beendet wird. Ich denke nicht, dass es eine gute Benutzerinteraktion ist, wenn eine App beendet wird. Daher gibt es keine Nice API dafür, nur die Home-Schaltfläche hat eine.

Wenn ein Fehler auftritt: Implementieren Sie ihn besser oder benachrichtigen Sie den Benutzer. Wenn ein Neustart erforderlich ist: Implementieren Sie dies besser, indem Sie den Benutzer benachrichtigen.

Es klingt dumm, aber es ist eine schlechte Praxis, die App zu beenden, ohne dass der Benutzer sich entscheidet und ihn nicht benachrichtigt. Und da es einen Home-Button für die Benutzerinteraktion gibt, Apple gibt an, dass es nicht zwei Dinge für dieselbe Funktion geben sollte (Beenden einer App).

0
Binarian

Beenden Sie eine App anders als mit der Startschaltfläche wirklich nicht iOS-artig.

Ich habe diesen Helfer gemacht, der keine privaten Sachen benutzt:

void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }

Aber in meinem Fall immer noch nicht für die Produktion gedacht. Es dient zum Testen von Absturzberichten oder zum schnellen Neustart nach einem Core Data-Reset. Es wurde nur darauf geachtet, nicht abgelehnt zu werden, wenn die Funktion im Produktionscode verbleibt.

0
Geri

Es kann sinnvoll sein, eine App zu beenden, wenn es sich um eine langlebige App handelt, die auch im Hintergrund ausgeführt wird, z. B. um Standortaktualisierungen abzurufen (mithilfe der Standortaktualisierungen Hintergrundfähigkeit dafür).

Angenommen, der Benutzer meldet sich von Ihrer standortbasierten App ab und verschiebt die App mithilfe der Startschaltfläche in den Hintergrund. In diesem Fall läuft Ihre App möglicherweise weiter, es kann jedoch sinnvoll sein, sie vollständig zu beenden. Dies ist gut für den Benutzer (gibt Speicher und andere Ressourcen frei, die nicht verwendet werden müssen) und gut für die Stabilität der App (z. B. Sicherstellen, dass die App regelmäßig neu gestartet wird, wenn dies möglich ist, ist ein Sicherheitsnetz gegen Speicherverluste und anderen niedrigen Speicherplatz Probleme).

Dies könnte (sollte aber wahrscheinlich nicht, siehe unten) erreicht werden mit etwas wie:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (/* logged out */) {
        exit(0);
    } else {
       // normal handling.
    }
}

Da die App dann den Hintergrund verlässt , sieht sie für den Benutzer nicht falsch aus und ähnelt keinem Absturz, sofern die Benutzeroberfläche wiederhergestellt wird Das nächste Mal, wenn sie die App ausführen. Mit anderen Worten, für den Benutzer würde es nicht anders aussehen als eine vom System eingeleitete Beendigung der App, wenn sich die App im Hintergrund befindet.

Es wäre jedoch vorzuziehen, einen Standardansatz zu verwenden, um das System darüber zu informieren, dass die App beendet werden kann. Beispiel: Stellen Sie in diesem Fall sicher, dass das GPS nicht verwendet wird, indem Sie keine Standortaktualisierungen mehr anfordern. Deaktivieren Sie beispielsweise die Option zum Anzeigen des aktuellen Standorts in einer Kartenansicht, falls vorhanden. Auf diese Weise beendet das System die App einige Minuten (d. H. [[UIApplication sharedApplication] backgroundTimeRemaining]), Nachdem die App in den Hintergrund eingetreten ist. Dies würde die gleichen Vorteile bringen, ohne Code zum Beenden der App verwenden zu müssen.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (/* logged out */) {
       // stop requesting location updates if not already done so
       // tidy up as app will soon be terminated (run a background task using beginBackgroundTaskWithExpirationHandler if needed).
    } else {
       // normal handling.
    }
}

Und natürlich wäre die Verwendung von exit(0) niemals für die durchschnittliche Produktions-App geeignet, die im Vordergrund ausgeführt wird, wie in anderen Antworten angegeben, auf die verwiesen wird http://developer.Apple.com/iphone/library) /qa/qa2008/qa1561.html

0
frankodwyer

Swift 4.2 (oder älter)

Bibliothek mit dem Namen Darvin kann verwendet werden.

import Darwin

exit(0) // Here you go

Hinweis: Dies wird in iOS-Anwendungen nicht empfohlen.

Auf diese Weise erhalten Sie das Absturzprotokoll.

0
Saranjith