Saya memprogram aplikasi iPhone, dan saya harus memaksanya untuk keluar karena tindakan pengguna tertentu. Setelah membersihkan memori yang dialokasikan aplikasi, metode apa yang tepat untuk memanggil untuk menghentikan aplikasi?
Saya memprogram aplikasi iPhone, dan saya harus memaksanya untuk keluar karena tindakan pengguna tertentu. Setelah membersihkan memori yang dialokasikan aplikasi, metode apa yang tepat untuk memanggil untuk menghentikan aplikasi?
Jawaban:
Sudahkah Anda mencoba exit(0)
?
Atau, [[NSThread mainThread] exit]
walaupun saya belum mencoba sepertinya solusi yang lebih tepat.
Di iPhone tidak ada konsep berhenti aplikasi. Satu-satunya tindakan yang menyebabkan aplikasi berhenti adalah menyentuh tombol Beranda di ponsel, dan itu bukan sesuatu yang dapat diakses pengembang.
Menurut Apple, aplikasi Anda seharusnya tidak berhenti dengan sendirinya. Karena pengguna tidak menekan tombol Beranda, setiap pengembalian ke layar Beranda memberi kesan pada pengguna bahwa aplikasi Anda mogok. Ini membingungkan, perilaku tidak standar dan harus dihindari.
keluar (0) muncul kepada pengguna sebagai macet, jadi tunjukkan pesan konfirmasi kepada pengguna. Setelah konfirmasi ditangguhkan (tombol home tekan secara programatis) dan tunggu 2 detik saat aplikasi berjalan dengan animasi kemudian keluar di belakang tampilan pengguna
-(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);
}
}
exit(0)
tidak masalah. Intinya aplikasi Anda memiliki "perilaku berhenti". Berhenti perilaku itu sendiri dilarang di AppStore kecuali beberapa aplikasi yang dibuat oleh pihak ketiga yang sangat penting. Selain itu, meniru perilaku tombol beranda juga dapat ditolak.
Periksa T&J di sini: https://developer.apple.com/library/content/qa/qa1561/_index.html
T: Bagaimana cara saya secara terprogram keluar dari aplikasi iOS?
Tidak ada API yang disediakan untuk menghentikan aplikasi iOS dengan anggun.
Di iOS, pengguna menekan tombol Rumah untuk menutup aplikasi. Jika aplikasi Anda memiliki kondisi di mana ia tidak dapat menyediakan fungsi yang dimaksud, pendekatan yang disarankan adalah menampilkan peringatan untuk pengguna yang menunjukkan sifat masalah dan tindakan yang mungkin dilakukan pengguna - menyalakan WiFi, mengaktifkan Layanan Lokasi, dll. Izinkan pengguna untuk menghentikan aplikasi atas kebijakan mereka sendiri.
PERINGATAN: Jangan panggil
exit
fungsi. Panggilan aplikasiexit
akan tampak bagi pengguna mengalami crash, daripada melakukan penghentian yang anggun dan menghidupkan kembali ke layar Beranda.Selain itu, data mungkin tidak disimpan, karena
-applicationWillTerminate:
dan serupaUIApplicationDelegate
metode tidak akan dipanggil jika Anda memanggil keluar.Jika selama pengembangan atau pengujian perlu untuk menghentikan aplikasi Anda,
abort
fungsi, atauassert
makro direkomendasikan
Ini bukan cara untuk keluar dari program, tetapi cara untuk memaksa orang untuk berhenti.
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];
Buka info.plist Anda dan centang tombol "Aplikasi tidak berjalan di latar belakang". Kali ini ketika pengguna mengklik tombol beranda, aplikasi keluar sepenuhnya.
Tambahkan UIApplicationExitsOnSuspend
properti application-info.plist
ke true
.
Setelah beberapa tes, saya dapat mengatakan yang berikut:
[UIApplication sharedApplication]
akan menyebabkan aplikasi tampak macet, TETAPI itu akan memanggil - (void)applicationWillTerminate:(UIApplication *)application
sebelum melakukannya;exit(0);
juga akan menghentikan aplikasi, tetapi akan terlihat "normal" (ikon loncatan muncul seperti yang diharapkan, dengan efek zoom out), TAPI itu tidak akan memanggil - (void)applicationWillTerminate:(UIApplication *)application
metode delegasi.Saranku:
- (void)applicationWillTerminate:(UIApplication *)application
delegasi secara manual.exit(0);
.Delegasi ApplicationAnda akan diberitahukan tentang pengunduran diri yang disengaja oleh pengguna:
- (void)applicationWillResignActive:(UIApplication *)application {
Ketika saya mendapatkan pemberitahuan ini, saya hanya menelepon
exit(0);
Yang melakukan semua pekerjaan. Dan yang terbaik adalah, itu adalah niat pengguna untuk berhenti, itulah mengapa ini seharusnya tidak menjadi masalah menyebutnya di sana.
Di Audio-App saya perlu untuk berhenti dari aplikasi setelah orang menyinkronkan perangkat mereka saat musik masih diputar. Segera setelah sinkronisasi selesai, saya mendapat pemberitahuan. Tetapi berhenti dari aplikasi setelah itu akan benar-benar terlihat seperti macet.
Jadi alih-alih saya menetapkan bendera untuk BENAR-BENAR keluar dari aplikasi pada tindakan latar belakang berikutnya. Yang oke untuk menyegarkan aplikasi setelah sinkronisasi.
Aplikasi saya baru-baru ini ditolak. Saya telah menggunakan metode tidak berdokumen. Secara harfiah:
"Sayangnya itu tidak dapat ditambahkan ke App Store karena menggunakan API pribadi. Penggunaan API non-publik, yang sebagaimana diuraikan dalam Perjanjian Lisensi Program Pengembang iPhone bagian 3.3.1 dilarang:
"3.3.1 Aplikasi hanya dapat menggunakan API Terdokumentasi dengan cara yang ditentukan oleh Apple dan tidak boleh menggunakan atau memanggil API pribadi apa pun."
API non-publik yang termasuk dalam aplikasi Anda adalah terminateWithSuccess "
Apple mengatakan:
"Peringatan: Jangan panggil fungsi keluar. Aplikasi yang memanggil keluar akan tampak bagi pengguna mengalami gangguan, alih-alih melakukan penghentian yang anggun dan menghidupkan kembali ke layar Beranda."
Saya pikir ini anggapan yang buruk. Jika pengguna mengetuk tombol keluar dan muncul pesan yang mengatakan sesuatu seperti: "Aplikasi sekarang akan keluar.", Sepertinya tidak macet. Apple harus menyediakan cara yang valid untuk keluar dari aplikasi (tidak keluar (0)).
Ini mendapatkan jawaban yang bagus tetapi memutuskan untuk sedikit memperluas:
Anda tidak bisa mendapatkan aplikasi Anda diterima di AppStore tanpa membaca Panduan Antarmuka Manusia iOS Apple dengan baik. (mereka memiliki hak untuk menolak Anda karena melakukan sesuatu yang melawan mereka) Bagian "Jangan Berhenti Secara Programatis" http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices. html adalah pedoman persis tentang bagaimana Anda harus memperlakukan dalam kasus ini.
Jika Anda pernah memiliki masalah dengan platform Apple yang tidak dapat Anda temukan solusinya dengan mudah, berkonsultasilah dengan HIG. Mungkin saja Apple tidak ingin Anda melakukannya dan mereka biasanya (saya bukan Apple jadi saya tidak bisa selalu menjamin) mengatakannya dalam dokumentasi mereka.
Hm, Anda mungkin 'harus' keluar dari aplikasi jika, katakanlah, aplikasi Anda memerlukan koneksi internet. Anda dapat menampilkan peringatan dan kemudian melakukan sesuatu seperti ini:
if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
[[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
kill(getpid(), SIGINT);
}
Kita tidak bisa berhenti aplikasi menggunakan exit(0)
, abort()
fungsi, seperti Apple sangat tidak menyarankan penggunaan fungsi-fungsi ini. Meskipun Anda dapat menggunakan fungsi ini untuk tujuan pengembangan atau pengujian.
Jika selama pengembangan atau pengujian perlu untuk menghentikan aplikasi Anda, fungsi batal, atau menegaskan makro dianjurkan
Silakan temukan utas T&J Apple ini untuk mendapatkan informasi lebih lanjut.
Seperti penggunaan fungsi ini, membuat kesan seperti aplikasi mogok. Jadi saya mendapat beberapa saran seperti kita dapat menampilkan Peringatan dengan pesan penghentian kepada pengguna yang sadar tentang menutup aplikasi, karena tidak tersedianya fungsi tertentu.
Tetapi Pedoman Antarmuka Manusia iOS untuk Memulai dan Menghentikan Aplikasi , menyarankan agar Jangan pernah menggunakan tombol Keluar atau Tutup untuk mengakhiri Aplikasi. Daripada itu mereka menyarankan untuk menampilkan pesan yang tepat untuk menjelaskan situasi.
Aplikasi iOS tidak pernah menampilkan opsi Tutup atau Keluar. Orang-orang berhenti menggunakan aplikasi ketika mereka beralih ke aplikasi lain, kembali ke layar Beranda, atau meletakkan perangkat mereka dalam mode tidur.
Jangan pernah berhenti dari aplikasi iOS secara terprogram. Orang-orang cenderung menafsirkan ini sebagai gangguan. Jika ada sesuatu yang mencegah aplikasi Anda berfungsi sebagaimana dimaksud, Anda harus memberi tahu pengguna tentang situasinya dan menjelaskan apa yang dapat mereka lakukan.
Selain jawaban di atas, bagus, saya hanya ingin menambahkan, pikirkan tentang membersihkan memori Anda.
Setelah aplikasi Anda keluar, iPhone OS akan secara otomatis membersihkan apa pun yang ditinggalkan aplikasi Anda, sehingga membebaskan semua memori secara manual hanya dapat menambah jumlah waktu yang dibutuhkan aplikasi Anda untuk keluar.
- (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);
}
}
Saya menggunakan pendekatan addObject: nil] yang disebutkan di atas untuk memaksa keluar (crash) aplikasi tanpa membuat panggilan fungsi keluar (0).
Mengapa? Karena aplikasi saya menggunakan pinning sertifikat pada semua panggilan API jaringan untuk mencegah serangan man-in-the-middle. Ini termasuk panggilan inisialisasi aplikasi finansial saya saat startup.
Jika otentikasi sertifikat gagal, semua panggilan inisialisasi saya salah dan biarkan aplikasi saya dalam keadaan tidak ditentukan. Membiarkan pengguna pulang dan kembali ke aplikasi tidak membantu, karena kecuali aplikasi telah dibersihkan oleh OS itu masih belum diinisialisasi dan tidak dapat dipercaya.
Jadi, dalam kasus ini, kami menganggap yang terbaik untuk mengeluarkan peringatan yang memberi tahu pengguna bahwa aplikasi beroperasi di lingkungan yang tidak aman dan kemudian, ketika mereka menekan "Tutup", paksa keluar dari aplikasi menggunakan metode yang disebutkan di atas.
[[UIApplication sharedApplication] terminateWithSuccess];
Ini berfungsi dengan baik dan secara otomatis memanggil
- (void)applicationWillTerminateUIApplication *)application delegate.
untuk menghapus kompilasi peringatan waktu tambahkan kode ini
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end
Anda tidak boleh langsung memanggil fungsi tersebut exit(0)
karena akan segera keluar dari aplikasi dan akan membuat aplikasi Anda mogok. Jadi lebih baik untuk menunjukkan kepada pengguna peringatan konfirmasi dan biarkan mereka melakukannya sendiri.
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()
}
}
Pengguna harus memutuskan kapan aplikasi keluar. Saya tidak berpikir itu adalah interaksi pengguna yang baik ketika aplikasi berhenti. Karena itu tidak ada API yang bagus untuk itu, hanya tombol beranda yang memilikinya.
Jika ada kesalahan: Terapkan lebih baik atau Beri tahu pengguna. Jika harus ada restart: Terapkan itu lebih baik dari Beri tahu pengguna.
Kedengarannya bodoh, tapi itu praktik buruk untuk keluar dari aplikasi tanpa membiarkan pengguna memutuskan dan tidak memberi tahu dia. Dan karena ada tombol beranda untuk interaksi pengguna, Apple menyatakan, seharusnya tidak ada 2 hal untuk fungsi yang sama (keluar dari aplikasi).
Keluar dari aplikasi selain dari tombol beranda benar-benar non-iOS-esque pendekatan yang .
Saya melakukan bantuan ini, yang tidak menggunakan barang pribadi:
void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }
Tapi tetap tidak dimaksudkan untuk produksi dalam kasus saya. Ini untuk menguji laporan kerusakan, atau untuk memulai kembali dengan cepat setelah reset Data Inti. Hanya membuatnya aman untuk tidak ditolak jika fungsi dibiarkan dalam kode produksi.
Di iPadOS 13 Anda sekarang dapat menutup semua sesi pemandangan seperti ini:
for session in UIApplication.shared.openSessions {
UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
}
Ini akan menelepon applicationWillTerminate(_ application: UIApplication)
delegasi aplikasi Anda dan mengakhiri aplikasi pada akhirnya.
Namun waspadalah terhadap dua hal:
Ini tentu saja tidak dimaksudkan untuk digunakan untuk menutup semua adegan. (lihat https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/multiple-windows/ )
Ini mengkompilasi dan berjalan dengan baik di iOS 13 pada iPhone, tetapi tampaknya tidak melakukan apa-apa.
Info lebih lanjut tentang adegan di iOS / iPadOS 13: https://developer.apple.com/documentation/uikit/app_and_environment/scenes
Mungkin tepat untuk keluar dari aplikasi jika itu adalah aplikasi berumur panjang yang juga dijalankan di latar belakang, misalnya untuk mendapatkan pembaruan lokasi (menggunakan pembaruan lokasi kemampuan latar belakang untuk itu).
Misalnya, katakanlah pengguna keluar dari aplikasi berbasis lokasi Anda, dan mendorong aplikasi ke latar belakang menggunakan tombol beranda. Dalam hal ini aplikasi Anda mungkin terus berjalan, tetapi masuk akal untuk sepenuhnya keluar. Ini akan baik untuk pengguna (melepaskan memori dan sumber daya lain yang tidak perlu digunakan), dan baik untuk stabilitas aplikasi (yaitu memastikan aplikasi secara berkala dimulai kembali jika memungkinkan adalah jaring pengaman terhadap kebocoran memori dan memori rendah lainnya. masalah).
Ini bisa (walaupun mungkin seharusnya tidak, lihat di bawah :-) dapat dicapai dengan sesuatu seperti:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (/* logged out */) {
exit(0);
} else {
// normal handling.
}
}
Karena aplikasi kemudian akan keluar dari latar belakang itu tidak akan terlihat salah bagi pengguna, dan tidak akan menyerupai crash, menyediakan antarmuka pengguna dipulihkan saat mereka menjalankan aplikasi berikutnya. Dengan kata lain, bagi pengguna itu tidak akan terlihat berbeda dengan sistem yang memulai penghentian aplikasi ketika aplikasi berada di latar belakang.
Namun, akan lebih baik menggunakan pendekatan yang lebih standar untuk membuat sistem tahu bahwa aplikasi dapat dihentikan. Misalnya dalam hal ini, dengan memastikan GPS tidak digunakan dengan menghentikan permintaan pembaruan lokasi, termasuk mematikan acara lokasi saat ini pada tampilan peta jika ada. Dengan cara itu sistem akan memberhentikan aplikasi beberapa menit (yaitu [[UIApplication sharedApplication] backgroundTimeRemaining]
) setelah aplikasi memasuki latar belakang. Ini akan mendapatkan semua manfaat yang sama tanpa harus menggunakan kode untuk menghentikan aplikasi.
- (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.
}
}
Dan tentu saja, menggunakan exit(0)
tidak akan pernah sesuai untuk aplikasi produksi rata-rata yang berjalan di latar depan, seperti jawaban lain yang merujuk http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html