iPhoneアプリケーションを終了する正しい方法?
-
21-08-2019 - |
質問
iPhone アプリをプログラミングしていますが、特定のユーザーのアクションによりアプリを強制終了する必要があります。アプリが割り当てたメモリをクリーンアップした後、アプリケーションを終了するために呼び出す適切なメソッドは何ですか?
解決
あなたはexit(0)
を試したことがありますか?
また、[[NSThread mainThread] exit]
、私はそれがより適切な解決策のように思えることを試していませんが。
他のヒント
は、iPhone上でアプリを終了する概念はありません。終了するアプリを起こす必要がある唯一のアクションは、携帯電話上のホームボタンをタッチしている、それは何かの開発者がアクセス権を持っていません。
アップルによると、アプリケーションが独自に終了するべきではありません。ユーザーがホームボタンをヒットしなかったので、ホーム画面への復帰は、ユーザーにアプリケーションがクラッシュした印象を与えます。これは混乱し、非標準的な動作であり、避けるべきである。
出口(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);
}
}
そのない、本当にプログラムを終了する方法が、終了して、人々を強制する方法。
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];
ここでQ&Aを確認してください: https://developer.apple.com /library/content/qa/qa1561/_index.htmlする
Q:どのように私はプログラム的に私のiOSアプリケーションを終了します。
優雅にiOSアプリケーションを終了するためありませんAPIはありません。
iOS版では、ユーザーがアプリケーションを終了してホームボタンを押します。あなたのアプリケーションは、それがその意図した機能を提供しないことが可能な条件を持っている必要があり、推奨されるアプローチは、ユーザーが取ることができる問題と可能なアクションの性質を示すユーザに対して警告を表示することがある - など、場所サービスを有効にする、無線LANをオンにしますユーザーが自分の裁量でアプリケーションを終了することを許可します。
あなたが終了を呼び出す場合の警告:の
exit
関数を呼び出さないでください。exit
を呼び出すアプリケーションは、むしろ優雅な終了を実行すると、ホーム画面に戻ってアニメーションよりも、クラッシュしたことがユーザーに表示されます。-applicationWillTerminate:
と同様のUIApplicationDelegate
メソッドが呼び出されることはありませんので、また、データは、保存されない場合があります。
が推奨される開発中か、あなたのアプリケーション、
abort
機能、またはassert
マクロを終了する必要があるテストの場合
あなたのInfo.plistに移動し、キーを確認する「アプリケーションはバックグラウンドで実行されません」。ユーザーは、ホームボタンをクリックする。この時間は、アプリケーションが完全に終了します。
UIApplicationExitsOnSuspend
するapplication-info.plist
にtrue
プロパティを追加します。
その後試験、言っているの
- 利用者インターフェース:
[UIApplication sharedApplication]
すると、アプリのような話ですが、通- (void)applicationWillTerminate:(UIApplication *)application
前に出ししていただくことになります。 - を使用
exit(0);
も終了させるアプリケーションですが、見えてしまう"通常"の踏み台のアイコンと同じように見えることになるの縮小効果がでないの- (void)applicationWillTerminate:(UIApplication *)application
委譲方法です。
私のアドバイス
- 手動で通話を
- (void)applicationWillTerminate:(UIApplication *)application
のに限ります。 - 電話
exit(0);
.
あなたのApplicationDelegateがユーザーによって意図的な辞職の通知を取得します:
- (void)applicationWillResignActive:(UIApplication *)application {
私は、この通知を取得すると、私はちょうど呼び出し
exit(0);
すべての作業を行い、どの。そして、最高のものは、そこにそれを呼び出す問題にはならない理由である、終了するuseresの意図でされます。
私のオーディオアプリ上では、音楽はまだ再生している間、人々が自分のデバイスを同期された後にアプリを終了する必要がありました。すぐに同期が完了すると、私は通知を取得します。しかし、その直後のアプリを終了すると、実際にクラッシュのようになります。
は、だからではなく、私は本当に、次のバックグラウンド化アクションでアプリを終了するフラグを設定します。これは同期の後にアプリをリフレッシュするため大丈夫です。
私のアプリは、私が文書化されていないメソッドを使用しました紀元前最近拒否されました。文字通ります:
。それはプライベートAPIを使用しているため、「残念ながら、それはApp Storeに追加することはできませんiPhoneデベロッパプログラムのライセンス契約のセクション3.3.1に概説されているよう非パブリックAPIの使用は禁止されています:
「3.3.1のみアップルで定める方法により文書化されたAPIを使用してアプリケーションと使用したり、任意のプライベートAPIを呼び出すことはできません。」
あなたのアプリケーションに含まれる非パブリックAPIは「terminateWithSuccessである
Appleは言う:
「警告:。。exit関数を呼び出してはいけないの出口を呼び出すアプリケーションは、むしろ優雅な終了を実行すると、ホーム画面に戻ってアニメーションよりも、クラッシュしたことがユーザーに表示されます」
私はこれは悪い仮定だと思います。ユーザーが終了ボタンをタップすると、メッセージが何か言う表示された場合:「アプリケーションは現在終了します」と、クラッシュしたことが表示されません。 Appleはアプリケーションを終了する有効な方法を提供しなければならない(しませ終了(0))。
これは良い答えを得て、少しを拡大することを決定しました。
あなたは、あなたのアプリケーションがうまくAppleのiOSのヒューマンインターフェイスガイドラインを読まずAppStoreのに受け入れられて取得することはできません。 (彼らはそれらに対しての何でものを行うためにあなたを拒否する権利を保有)のセクションは、「プログラムを終了しないでください」<のhref = "http://developer.apple.com/library/ios/# DOCUMENTATION / UserExperience /概念/ MobileHIG / UEBestPractices / UEBestPractices.html」のrel = "nofollowを"> http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html あなたは、この場合に扱うべきかの正確なガイドラインがあります。
あなたは今まであなたが簡単のために解決策を見つけることができませんアップルのプラットフォームに問題がある場合は、、HIGを参照してください。これは、Appleが単にあなたがそれを行うにはしたくありませんし、通常、彼らは(私は常に保証することはできませんので、私はアップルではないよ)自分のドキュメントにそう言うんことが可能です。
私たちは、exit(0)
、abort()
機能を使ってアプリを終了することはできません。あなたは、開発やテストの目的のために、この機能を使用することができますが。
あなたを終了する必要があり、開発中やテストの場合 アプリケーション、アボート機能、またはアサートマクロが推奨される
このアップル Q&より多くの情報を得るためにのスレッドを見つけてください。ます。
この機能の使用などのアプリケーションのような印象クラッシュさを作成します。だから私たちは原因特定の機能が利用できないため、アプリを閉じに関する意識ユーザーに終了メッセージと警告を表示することができますようにいくつかの提案を持っています。
しかし、 に、それを示唆してのアプリケーションを終了させる終了または閉じるボタンを使用しないでください。むしろ、彼らは状況を説明するために、適切なメッセージを表示するように示唆されていること。
iOSアプリは閉じるか、終了オプションを表示することはありません。人々は使用を中止します 彼らは別のアプリに切り替えるとアプリは、ホーム画面に戻り、または置きます スリープモードで自分のデバイスます。
は、プログラムでiOSアプリを終了することはありません。人々はこれを解釈する傾向があります クラッシュなど。何かがとしての機能からあなたのアプリを防ぎ場合 意図した、あなたは状況についてユーザーに通知し、説明するために必要なもの 彼らはそれについて行うことができます。
上記の、良い、答えに加えて、私はちょうどあなたのメモリをクリーンアップについて考え、追加したい。
あなたのアプリケーションが終了した後、iPhone OSが自動的ので、ちょうどそれが終了し、アプリケーションにかかる時間の量を増やすことができ、手動ですべてのメモリを解放し、あなたのアプリケーションが残した何かをクリーンアップします。
フム、あなたが言う、あなたのアプリケーションは、インターネット接続が必要、場合、アプリケーションを終了「しなければならない」ことがあります。あなたは警告を表示し、このような何かを行うことができます:
if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
[[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
kill(getpid(), SIGINT);
}
- (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);
}
}
私は[ゼロ[NSMutableArrayの新しい]のaddObject]を使用していました。
なぜ?私のアプリは、すべてのネットワークAPIの証明書ピニングを使用しているため、man-in-the-middle攻撃を防ぐために呼び出します。これらは、初期化が私の金融アプリは、起動時に実行するコール含まれています。
証明書の認証に失敗した場合は、は、私の初期設定のすべてがエラーアウト呼び出し、不確定な状態で私のアプリを残します。ユーザーが戻ってアプリにその後、家に帰るとまかせアプリは、それはまだ初期化されていないと信用できないですOSによってパージされていない場合として、助けにはなりません。
だから、この一つのケースでは、我々は、彼らが「閉じる」を打ったときのアプリは、その後、安全でない環境で動作していることをユーザーに通知する警告をポップアップ表示するのが最善それをみなし、力を上記の方法を使用してアプリを終了します。
[[UIApplication sharedApplication] terminateWithSuccess];
それはうまく働いたと自動的に呼び出されます。
- (void)applicationWillTerminateUIApplication *)application delegate.
このコードを追加し、コンパイル時の警告を削除するには、
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end
ユーザーは、いつのアプリの終了を決定する必要があります。 私はアプリが終了したときに、それは良いユーザーとの対話ではないと思います。そのためには素敵なAPIが存在しない、唯一のホームボタンが1つを持っています。
エラーがある場合:より良い、それを実装するか、ユーザーに通知します。 再起動があるようにしている場合:それはより良いユーザーに通知の実装
。これは、ダムに聞こえるが、それはユーザーが決めるせ、彼を通知しないことなく、アプリを終了するには、悪い習慣です。ユーザーとの対話のためのホームボタン、アップルの状態があるので、同じ機能(アプリを終了する)ための2つのことがあってはならない。
ホームボタンの本当に非のiOS風のアプローチよりも、他の方法でアプリを終了します。
私は民間のものを使用していないものの、このヘルパーを、やりました
void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }
しかし、まだ私の場合は生産のためのものではありません。これは、コアデータのリセット後にクラッシュreportingsをテストするための、または高速再起動することです。ただ、機能は製品コードに残っている場合、それは安全で拒否されないようにしてます。
スイフト4.2(またはそれ以前)
Darvin
と呼ばれるライブラリを使用することができます。
import Darwin
exit(0) // Here you go
NB:これはiOSアプリケーションにrecomandedされていません。
これを行うと、あなたのクラッシュログを取得します。
あなたは直接、関数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);
存続期間が長く、バックグラウンドでも実行されるアプリの場合、たとえば、位置情報の更新を取得する( 位置情報の更新 そのためのバックグラウンド機能)。
たとえば、ユーザーが位置情報ベースのアプリからログアウトし、ホーム ボタンを使用してアプリをバックグラウンドにプッシュしたとします。この場合、アプリは実行し続ける可能性がありますが、完全に終了することが合理的である可能性があります。これはユーザーにとっても良いこと (メモリやその他の使用する必要のないリソースが解放されること)、またアプリの安定性にとっても良いこと (つまり、可能であればアプリを定期的に再起動することは、メモリ リークやその他のメモリ不足の問題に対するセーフティ ネットです)。
これは次のようなもので実現できます (おそらくそうすべきではありませんが、以下を参照:-):
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (/* logged out */) {
exit(0);
} else {
// normal handling.
}
}
そうするとアプリが終了してしまうので、 背景から外れた 次回アプリを実行するときにユーザー インターフェイスが復元される限り、ユーザーには問題があるようには見えず、クラッシュにも似ていません。言い換えれば、ユーザーにとっては、アプリがバックグラウンドにあるときにシステムが開始したアプリの終了と何ら変わらないように見えます。
それでも、より標準的なアプローチを使用して、アプリを終了できることをシステムに知らせることが望ましいでしょう。たとえば、この場合、地図ビュー上で現在位置の表示をオフにするなど、位置更新の要求を停止して 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