web-dev-qa-db-ja.com

iPhoneアプリケーションを終了するための適切な方法は?

私はiPhoneアプリをプログラミングしています、そして私はそれが特定のユーザーの行動のために強制的に終了する必要があります。アプリケーションが割り当てたメモリをクリーンアップした後、アプリケーションを終了するために呼び出す適切な方法は何ですか?

264
user21293

exit(0)を試しましたか?

代わりに、[[NSThread mainThread] exit]、私はそれがより適切な解決策のように思えることを試みませんでしたが。

212
Brett

IPhoneでは、アプリを終了するという概念はありません。アプリを終了させる唯一のアクションは、電話のホームボタンを押すことです。これは開発者がアクセスできるものではありません。

Appleによると、あなたのアプリはそれだけで終了してはいけません。ユーザーがホームボタンを押していないため、ホーム画面に戻っても、アプリがクラッシュしたという印象をユーザーに与えます。これは混乱を招くような非標準的な動作であり、避けるべきです。

270
August

ユーザーにexit(0)がクラッシュしたように見えるので、ユーザーに確認メッセージを表示します。確認後(プログラムでホームボタンを押して)中断し、アプリがアニメーションでバックグラウンドになっている間に2秒間待ってから、ユーザーの目の前で終了します

-(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);
    }
}
47
Salim

これは実際にプログラムを終了する方法ではなく、人々を強制的に終了させる方法です。

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];
38
cwe7976

ここでQ&Aをチェックしてください: https://developer.Apple.com/library/content/qa/qa1561/index.html

Q:iOSアプリケーションをプログラムで終了するにはどうすればいいですか?

IOSアプリケーションを正常に終了するためのAPIは提供されていません。

IOSでは、ユーザーはホームボタンを押してアプリケーションを閉じます。アプリケーションが意図した機能を提供できない条件がある場合、推奨される方法は、問題の性質とユーザーが実行できる可能性のあるアクションを示すアラートをユーザーに表示することです。ユーザーが独自の判断でアプリケーションを終了できるようにします。

警告:exit関数を呼び出さないでください。 exitを呼び出すアプリケーションは、正常終了を実行してホーム画面にアニメーション表示するのではなく、クラッシュしたようにユーザーに表示されます。

さらに、exitを呼び出しても-applicationWillTerminate:および同様のUIApplicationDelegateメソッドが呼び出されないため、データが保存されない可能性があります。

開発またはテスト中にアプリケーションを終了する必要がある場合は、abort関数、またはassertマクロをお勧めします。

38
Wagh

Info.plistに行き、「アプリケーションがバックグラウンドで実行されない」というキーを確認してください。ユーザーがホームボタンをクリックすると、アプリケーションは完全に終了します。

38
Kalyan

application-info.plistUIApplicationExitsOnSuspendプロパティをtrueに追加します。

17
Aman Agarwal

いくつかのテストの後、私は次のように言うことができます。

  • プライベートインターフェースを使用する:[UIApplication sharedApplication]はアプリがクラッシュしたように見せますが、そうする前に- (void)applicationWillTerminate:(UIApplication *)applicationを呼び出します。
  • exit(0);を使用してもアプリケーションは終了しますが、それは "普通の"ように見えます(ズームアウト効果で、スプリングボードのアイコンは期待通りに表示されます)、しかし- (void)applicationWillTerminate:(UIApplication *)applicationデリゲートメソッドは呼び出しません。

私のアドバイス:

  1. デリゲートで- (void)applicationWillTerminate:(UIApplication *)applicationを手動で呼び出します。
  2. exit(0);を呼び出します。
13
rchampourlier

あなたのApplicationDelegateは、ユーザーによる意図的な終了を通知されます。

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

この通知を受け取ったら、電話をかけるだけです。

        exit(0);

これですべての作業が終わりました。そして最良のことは、それは終了することをユーザが意図していることです。

私のオーディオアプリでは、音楽がまだ再生されている間に人々が自分のデバイスを同期した後にアプリを終了する必要がありました。同期が完了するとすぐに通知が届きます。しかし、その直後にアプリを終了すると、実際にはクラッシュしたように見えます。

そのため、代わりに次のバックグラウンドアクションでアプリを本当に終了するようにフラグを設定しました。同期後にアプリを更新しても問題ありません。

8
L'g

私のアプリは最近拒否されましたbc私は文書化されていない方法を使用しました。文字通り:

「残念ながら、プライベートAPIを使用しているためApp Storeに追加できません。iPhoneデベロッパープログラム使用許諾契約書のセクション3.3.1で概説されているように、非公開APIの使用は禁止されています。

「3.3.1アプリケーションは、アップルが規定する方法で文書化されたAPIのみを使用することができ、プライベートAPIを使用または呼び出してはなりません。」

アプリケーションに含まれている非公開APIはterminateWithSuccessです。

6
user223106

アップルは言う:

「警告:exit関数を呼び出さないでください。exitを呼び出すアプリケーションは、正常に終了してホーム画面に戻ってアニメーション化するのではなく、クラッシュしたように見えます。」

これは悪い仮定だと思います。ユーザーが終了ボタンをタップして、「アプリケーションは終了します。」のようなメッセージが表示されても、クラッシュしているようには見えません。 Appleはアプリケーションを終了する有効な方法を提供するべきです(exit(0)ではありません)。

6
AGPX

これで良い答えが得られましたが、少し拡張することにしました。

AppleのiOS Human Interface Guidelinesをよく読まなければ、アプリケーションをAppStoreに受け入れさせることはできません。 (彼らはあなたに対して何かに対してそれらをすることを拒絶する権利を保持します)セクション「プログラム的に終了しないでください」 http:// developer .Apple.com/library/ios /#ドキュメント/ UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html は、この場合の対処方法の正確なガイドラインです。

あなたがAppleプラットフォームに問題を抱えたことがあるならば、あなたは簡単に解決策を見つけることができません、HIGに相談してください。 Appleがあなたにそれをしてほしくないことは可能であり、彼らは通常(私はAppleではないので私はいつも保証することはできない)彼らの文書でそう言う。

4
nanonyme

exit(0)abort()関数を使ってアプリを終了することはできません。Appleはこれらの関数の使用を推奨していません。あなたは開発やテストの目的のためにこの機能を使用することができますが。

開発中またはテスト中にアプリケーションを終了する必要がある場合は、中止関数またはassertマクロをお勧めします。

より多くの情報を得るためにこのApple Q&A スレッドを見つけてください。

この機能を使うとアプリケーションがクラッシュするような印象を与えます。そのため、特定の機能が利用できないために、アプリケーションの終了についてユーザーに通知するためのアラートを終了メッセージ付きで表示できるように、いくつか提案があります。

しかし、iOSヒューマンインタフェースガイドライン アプリの起動と停止 から、[終了]または[閉じる]ボタンを使用してアプリケーションを終了することは絶対に避けてください。それどころか、彼らは状況を説明するために適切なメッセージを表示することを提案しているということです。

IOSアプリは、閉じるまたは終了オプションを表示しません。他のアプリに切り替えたり、ホーム画面に戻ったり、デバイスをスリープモードにしたりすると、アプリの使用を中止します。

プログラムでiOSアプリを終了しないでください。人々はこれをクラッシュと解釈する傾向があります。アプリが意図したとおりに機能しなくなった場合は、状況をユーザーに知らせて、ユーザーが状況に対して何ができるかを説明する必要があります。

3
technerd

上記に加えて、良い、私がちょうど加えたいと思う答え、あなたの記憶を片付けることについて考えなさい。

アプリケーションが終了すると、iPhone OSはアプリケーションが残したものを自動的にクリーンアップします。そのため、手動ですべてのメモリを解放すると、アプリケーションの終了にかかる時間が長くなります。

2
Chris Jefferson

ええと、あなたのアプリケーションがインターネット接続を必要とするなら、あなたはアプリケーションを「終了」しなければならないかもしれません。アラートを表示してから、次のようにすることができます。

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

上記の[[NSMutableArray new] addObject:nil]アプローチを使用して、わかりやすいexit(0)関数呼び出しを行わずにアプリを強制終了(クラッシュ)させました。

どうして?私のアプリは、中間者攻撃を防ぐためにすべてのネットワークAPI呼び出しで証明書固定を使用しているためです。これらは私の会計アプリが起動時に行う初期化呼び出しを含みます。

証明書の認証に失敗した場合、初期化呼び出しはすべてエラーとなり、アプリは未確定の状態になります。アプリがOSによって削除されていない限り、初期化されておらず信頼できないため、ユーザーを家に帰らせてアプリに戻すことは役に立ちません。

そのため、この場合は、アプリが安全でない環境で動作していることをユーザーに知らせる警告を表示し、[閉じる]をクリックしたときに前述の方法でアプリを強制終了することをお勧めします。

1
Michael Long
[[UIApplication sharedApplication] terminateWithSuccess];

それはうまく働き、自動的に電話をかけます

- (void)applicationWillTerminateUIApplication *)application delegate.

このコードを追加してコンパイル時の警告を削除する

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

関数exit(0)を直接呼び出さないでください。アプリケーションがすぐに終了し、アプリケーションがクラッシュしたように見えます。ユーザーに確認の警告を表示して、ユーザーに確認させるのがよいでしょう。

スイフト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)
}

使用法:

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

ユーザーはアプリがいつ終了するかを決定する必要があります。私は、アプリが終了したときにそれが良いユーザーインタラクションではないと思います。そのため、Nice APIはありません。ホームボタンだけがあります。

エラーがある場合:それをより良く実装するかユーザに通知してください。再起動する必要がある場合は、次の手順を実行します。ユーザーに通知することを推奨します。

それは愚かに聞こえますが、ユーザーに決定をさせて通知せずにアプリを終了するのは悪い習慣です。ユーザーインタラクションのためのホームボタンがあるので、Appleは同じ機能のために2つのことがあるべきではない(アプリを終了する)。

0
Binarian

ホームボタン以外の方法でアプリを終了するのは本当にiOSに非公開アプローチです。

私はこのヘルパーをしました、しかし、それは個人的なものを使用しません:

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

それでも私の場合は制作用ではありません。クラッシュレポートをテストするため、またはコアデータをリセットした後にすばやく再起動するためです。機能が製品コードに残っていても拒否されないように安全にしました。

0
Geri

例えば位置情報の更新を取得するために(location updatesバックグラウンド機能を使用するなど)、バックグラウンドでも実行される長命のアプリの場合は、アプリを終了することが適切な場合があります。

たとえば、ユーザーが場所ベースのアプリからログアウトし、ホームボタンを使用してアプリをバックグラウンドにプッシュするとします。この場合、アプリは実行し続けることができますが、完全に終了させることは意味があります。これはユーザーにとっては良いことであり(使用する必要のないメモリと他のリソースを解放すること)、そしてアプリの安定性にとっては良いことです(すなわち、可能なときにアプリを定期的に再起動することはメモリリークと他の低メモリに対する安全策です)問題)。

これは(おそらくそうすべきではありませんが、下記を参照してください:-)次のようなもので達成できます。

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

その場合、アプリは終了しますout of backgroundユーザーには間違って見えず、クラッシュに似ていません。ユーザーが次回アプリを実行したときにユーザーインターフェイスが復元されます。言い換えれば、ユーザーには、アプリがバックグラウンドにあるときにシステムが開始したアプリの終了と何の違いもないように見えます。

それでも、アプリを終了できることをシステムに知らせるには、より標準的な方法を使用することをお勧めします。たとえば、この場合は、位置情報の更新要求を停止して、GPSが使用されていないことを確認します(存在する場合は、マップビューに現在位置を表示しないようにするなど)。このようにして、システムは、アプリがバックグラウンドに入った数分後にアプリを終了させるようにします(つまり[[UIApplication sharedApplication] backgroundTimeRemaining])。アプリを終了するためにコードを使用する必要なしにこれはすべて同じ利点を得るでしょう。

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

そしてもちろん、exit(0)を使うことはフォアグラウンドで動く平均的なプロダクションアプリにはふさわしくないでしょう、 http://developer.Apple.com/iphone/library/ qa/qa2008/qa1561.html

0
frankodwyer

Swift 4.2(またはそれ以上)

Darvinというライブラリを使用できます。

import Darwin

exit(0) // Here you go

注意:これはiOSアプリケーションでは推奨されていません。

こうするとクラッシュログになります。

0
Saranjith