Tôi đang lập trình một ứng dụng cho iPhone và tôi cần buộc nó thoát ra do một số hành động của người dùng. Sau khi dọn dẹp bộ nhớ ứng dụng được phân bổ, phương thức thích hợp để gọi để chấm dứt ứng dụng là gì?
Tôi đang lập trình một ứng dụng cho iPhone và tôi cần buộc nó thoát ra do một số hành động của người dùng. Sau khi dọn dẹp bộ nhớ ứng dụng được phân bổ, phương thức thích hợp để gọi để chấm dứt ứng dụng là gì?
Câu trả lời:
Bạn đã thử chưa exit(0)
chưa
Ngoài ra, [[NSThread mainThread] exit]
mặc dù tôi đã không thử rằng nó có vẻ như là giải pháp phù hợp hơn.
Trên iPhone không có khái niệm bỏ ứng dụng. Hành động duy nhất khiến ứng dụng thoát ra là chạm vào nút Home trên điện thoại và đó không phải là thứ mà các nhà phát triển có quyền truy cập.
Theo Apple, ứng dụng của bạn không nên tự chấm dứt. Vì người dùng không nhấn nút Home, bất kỳ quay lại màn hình chính nào cũng mang lại cho người dùng cảm giác ứng dụng của bạn bị sập. Điều này gây nhầm lẫn, hành vi không chuẩn và nên tránh.
exit (0) xuất hiện cho người dùng khi gặp sự cố, vì vậy hãy hiển thị thông báo xác nhận cho người dùng. Sau khi tạm dừng xác nhận (nhấn nút Home lập trình) và đợi 2 giây trong khi ứng dụng đang chạy nền với hình động rồi thoát ra sau chế độ xem của người dùng
-(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)
không thành vấn đề. Điểm là ứng dụng của bạn có "hành vi bỏ". Tự bỏ hành vi bị cấm trong AppStore ngoại trừ một vài ứng dụng được tạo bởi các bên thứ 3 rất quan trọng. Ngoài ra, bắt chước hành vi nút home cũng có thể bị từ chối.
Kiểm tra Q & A tại đây: https://developer.apple.com/l Library / content / qa / qa1561 / _index.html
H: Làm thế nào để tôi lập trình thoát khỏi ứng dụng iOS của mình?
Không có API nào được cung cấp để kết thúc một ứng dụng iOS một cách duyên dáng.
Trong iOS, người dùng nhấn nút Home để đóng ứng dụng. Nếu ứng dụng của bạn có các điều kiện không thể cung cấp chức năng dự định, cách tiếp cận được đề xuất là hiển thị cảnh báo cho người dùng cho biết bản chất của sự cố và các hành động có thể có mà người dùng có thể thực hiện - bật WiFi, bật Dịch vụ vị trí, v.v. Cho phép người dùng chấm dứt ứng dụng theo ý riêng của họ.
CẢNH BÁO: Không gọi
exit
chức năng. Các ứng dụng gọi điệnexit
sẽ xuất hiện khiến người dùng gặp sự cố, thay vì thực hiện chấm dứt duyên dáng và hoạt hình trở lại màn hình chính.Ngoài ra, dữ liệu có thể không được lưu, bởi vì
-applicationWillTerminate:
và cácUIApplicationDelegate
phương thức tương tự sẽ không được gọi nếu bạn gọi thoát.Nếu trong quá trình phát triển hoặc thử nghiệm, cần phải chấm dứt ứng dụng của bạn,
abort
chức năng hoặcassert
macro được khuyến nghị
Nó không thực sự là một cách để thoát khỏi chương trình, nhưng là một cách để buộc mọi người bỏ.
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];
Truy cập thông tin của bạn.plist và kiểm tra khóa "Ứng dụng không chạy trong nền". Lần này khi người dùng nhấp vào nút home, ứng dụng sẽ thoát hoàn toàn.
Thêm UIApplicationExitsOnSuspend
tài sản trên application-info.plist
đến true
.
Sau một số thử nghiệm, tôi có thể nói như sau:
[UIApplication sharedApplication]
sẽ khiến ứng dụng trông như bị sập, NHƯNG nó sẽ gọi- (void)applicationWillTerminate:(UIApplication *)application
trước khi thực hiện;exit(0);
cũng sẽ chấm dứt ứng dụng, nhưng nó sẽ trông "bình thường" (các biểu tượng của springboard xuất hiện như mong đợi, với hiệu ứng thu nhỏ), NHƯNG nó sẽ không gọi - (void)applicationWillTerminate:(UIApplication *)application
phương thức ủy nhiệm.Lời khuyên của tôi:
- (void)applicationWillTerminate:(UIApplication *)application
trên đại biểu.exit(0);
.ApplicationDelegate của bạn được thông báo về việc bỏ ý định của người dùng:
- (void)applicationWillResignActive:(UIApplication *)application {
Khi tôi nhận được thông báo này, tôi chỉ cần gọi
exit(0);
Mà làm tất cả các công việc. Và điều tốt nhất là, đó là ý định của người dùng để thoát, đó là lý do tại sao điều này không phải là một vấn đề gọi nó ở đó.
Trên Ứng dụng âm thanh của tôi, cần phải thoát ứng dụng sau khi mọi người đồng bộ hóa thiết bị của họ trong khi nhạc vẫn đang phát. Ngay sau khi đồng bộ hóa hoàn tất, tôi nhận được thông báo. Nhưng việc thoát khỏi ứng dụng ngay sau đó sẽ thực sự giống như một sự cố.
Vì vậy, thay vào đó tôi đặt cờ để THỰC SỰ thoát khỏi ứng dụng trên hành động nền tiếp theo. Không sao để làm mới ứng dụng sau khi đồng bộ hóa.
Ứng dụng của tôi đã bị từ chối gần đây bc Tôi đã sử dụng một phương pháp không có giấy tờ. Nghĩa đen
"Thật không may, nó không thể được thêm vào App Store vì nó đang sử dụng API riêng. Sử dụng các API không công khai, như được nêu trong Thỏa thuận cấp phép chương trình dành cho nhà phát triển iPhone phần 3.3.1 bị cấm:
"3.3.1 Ứng dụng chỉ có thể sử dụng API tài liệu theo cách do Apple quy định và không được sử dụng hoặc gọi bất kỳ API riêng tư nào."
API không công khai được bao gồm trong ứng dụng của bạn bị chấm dứtWithSuccess "
Apple nói:
"Cảnh báo: Không gọi chức năng thoát. Các ứng dụng gọi thoát sẽ xuất hiện khiến người dùng gặp sự cố, thay vì thực hiện chấm dứt duyên dáng và hoạt hình trở lại Màn hình chính."
Tôi nghĩ rằng đây là một giả định xấu. Nếu người dùng chạm vào nút thoát và một thông báo xuất hiện có nội dung như: "Ứng dụng sẽ thoát.", Nó dường như không bị sập. Apple nên cung cấp một cách hợp lệ để thoát khỏi một ứng dụng (không thoát (0)).
Điều này đã nhận được một câu trả lời tốt nhưng quyết định mở rộng một chút:
Bạn không thể chấp nhận ứng dụng của mình vào AppStore mà không cần đọc Nguyên tắc giao diện con người iOS của Apple. (họ có quyền từ chối bạn vì đã làm bất cứ điều gì chống lại họ) Phần "Đừng bỏ chương trình" http://developer.apple.com/l Library / ios html là một hướng dẫn chính xác về cách bạn nên đối xử trong trường hợp này.
Nếu bạn gặp sự cố với nền tảng Apple, bạn không thể dễ dàng tìm ra giải pháp cho, hãy tham khảo HIG. Có thể Apple đơn giản là không muốn bạn làm điều đó và họ thường (Tôi không phải là Apple nên tôi không thể đảm bảo luôn) nói như vậy trong tài liệu của họ.
Hừm, bạn có thể 'phải' thoát khỏi ứng dụng nếu, giả sử, ứng dụng của bạn yêu cầu kết nối internet. Bạn có thể hiển thị một cảnh báo và sau đó làm một cái gì đó như thế này:
if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
[[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
kill(getpid(), SIGINT);
}
Chúng ta không thể bỏ ứng dụng sử dụng exit(0)
, abort()
chức năng, như Apple ngăn cản mạnh mẽ việc sử dụng các chức năng này. Mặc dù bạn có thể sử dụng chức năng này cho mục đích phát triển hoặc thử nghiệm.
Nếu trong quá trình phát triển hoặc thử nghiệm cần phải chấm dứt ứng dụng của bạn, chức năng hủy bỏ hoặc xác nhận macro được khuyến nghị
Vui lòng tìm chủ đề Hỏi & Đáp này của Apple để có thêm thông tin.
Khi sử dụng chức năng này tạo ấn tượng như ứng dụng đang bị sập. Vì vậy, tôi đã nhận được một số đề xuất như chúng tôi có thể hiển thị Thông báo với thông báo chấm dứt để người dùng biết về việc đóng ứng dụng, do không có chức năng nhất định.
Nhưng Hướng dẫn Giao diện Con người iOS để Bắt đầu và Dừng Ứng dụng , đề nghị Không bao giờ sử dụng nút Thoát hoặc Đóng để chấm dứt Ứng dụng. Thay vào đó sau đó họ đang đề nghị hiển thị thông điệp thích hợp để giải thích tình huống.
Ứng dụng iOS không bao giờ hiển thị tùy chọn Đóng hoặc Thoát. Mọi người ngừng sử dụng một ứng dụng khi họ chuyển sang một ứng dụng khác, quay lại Màn hình chính hoặc đặt thiết bị của họ ở chế độ ngủ.
Không bao giờ thoát khỏi ứng dụng iOS theo chương trình. Mọi người có xu hướng giải thích điều này như một vụ tai nạn. Nếu một cái gì đó ngăn ứng dụng của bạn hoạt động như dự định, bạn cần nói với người dùng về tình huống và giải thích những gì họ có thể làm về nó.
Ngoài những điều trên, tốt, câu trả lời tôi chỉ muốn thêm, suy nghĩ về việc làm sạch bộ nhớ của bạn.
Sau khi ứng dụng của bạn thoát, HĐH iPhone sẽ tự động dọn sạch mọi thứ mà ứng dụng của bạn để lại, do đó giải phóng tất cả bộ nhớ theo cách thủ công chỉ có thể tăng thời gian ứng dụng của bạn thoát ra.
- (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);
}
}
Tôi đã sử dụng phương pháp [[NSMutableArray new] addObject: nil] được đề cập ở trên để buộc thoát (sự cố) ứng dụng mà không thực hiện cuộc gọi hàm thoát (0).
Tại sao? Bởi vì ứng dụng của tôi sử dụng ghim chứng chỉ trên tất cả các lệnh gọi API mạng để ngăn chặn các cuộc tấn công trung gian. Chúng bao gồm các cuộc gọi khởi tạo mà ứng dụng tài chính của tôi thực hiện khi khởi động.
Nếu xác thực chứng chỉ không thành công, tất cả các cuộc gọi khởi tạo của tôi đều bị lỗi và khiến ứng dụng của tôi ở trạng thái không xác định. Để người dùng về nhà và sau đó quay lại ứng dụng sẽ không giúp ích gì, trừ khi ứng dụng đã bị HĐH thanh trừng, nó vẫn chưa được xử lý và không đáng tin cậy.
Vì vậy, trong trường hợp này, chúng tôi cho rằng tốt nhất nên bật một cảnh báo thông báo cho người dùng rằng ứng dụng đang hoạt động trong môi trường không an toàn và sau đó, khi họ nhấn "Đóng", buộc thoát ứng dụng bằng phương pháp đã nói ở trên.
[[UIApplication sharedApplication] terminateWithSuccess];
Nó hoạt động tốt và tự động gọi
- (void)applicationWillTerminateUIApplication *)application delegate.
để loại bỏ cảnh báo thời gian biên dịch thêm mã này
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end
Bạn không nên gọi trực tiếp chức năng exit(0)
vì nó sẽ thoát ứng dụng ngay lập tức và sẽ có vẻ như ứng dụng của bạn bị sập. Vì vậy, tốt hơn để hiển thị cho người dùng một cảnh báo xác nhận và để họ tự làm điều này.
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()
}
}
Người dùng nên quyết định khi thoát ứng dụng. Tôi không nghĩ rằng đó là một tương tác người dùng tốt khi một ứng dụng thoát. Do đó, không có API đẹp cho nó, chỉ có nút home có một.
Nếu có lỗi: Triển khai nó tốt hơn hoặc Thông báo cho người dùng. Nếu phải có khởi động lại: Thực hiện tốt hơn thông báo cho người dùng.
Nghe có vẻ ngu ngốc, nhưng đó là thực tế xấu để thoát khỏi ứng dụng mà không để người dùng quyết định và không thông báo cho anh ta. Và vì có một nút home cho sự tương tác của người dùng, Apple tuyên bố, không nên có 2 điều cho cùng một chức năng (thoát khỏi một ứng dụng).
Thoát một ứng dụng theo cách khác ngoài nút home thực sự không phải là iOS-esque cách tiếp cận .
Tôi đã làm người trợ giúp này, mặc dù, không sử dụng những thứ riêng tư:
void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }
Nhưng vẫn không có nghĩa là để sản xuất trong trường hợp của tôi. Nó là để thử nghiệm các báo cáo sự cố hoặc để khởi động lại nhanh sau khi thiết lập lại Dữ liệu lõi. Chỉ cần làm cho nó an toàn không bị từ chối nếu chức năng còn lại trong mã sản xuất.
Trong iPadOS 13, giờ đây bạn có thể đóng tất cả các phiên cảnh như thế này:
for session in UIApplication.shared.openSessions {
UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
}
Cái này sẽ gọi applicationWillTerminate(_ application: UIApplication)
đại biểu ứng dụng của bạn và chấm dứt ứng dụng cuối cùng.
Nhưng hãy cẩn thận với hai điều:
Điều này chắc chắn không có nghĩa là được sử dụng để đóng tất cả các cảnh. (xem https://developer.apple.com/design/human-interface-guferences/ios/system-capabilities/mult Môn-windows / )
Nó biên dịch và chạy tốt trên iOS 13 trên iPhone, nhưng dường như không làm gì cả.
Thông tin thêm về các cảnh trong iOS / iPadOS 13: https://developer.apple.com/documentation/uikit/app_and_envir/scenes
Có thể thích hợp để thoát khỏi một ứng dụng nếu đó là một ứng dụng tồn tại lâu cũng thực thi trong nền, ví dụ để có được các cập nhật vị trí (sử dụng các cập nhật vị trí khả năng cho điều đó).
Ví dụ: giả sử người dùng đăng xuất khỏi ứng dụng dựa trên vị trí của bạn và đẩy ứng dụng xuống nền bằng nút home. Trong trường hợp này, ứng dụng của bạn có thể tiếp tục chạy, nhưng có thể thoát khỏi nó hoàn toàn có ý nghĩa. Nó sẽ tốt cho người dùng (giải phóng bộ nhớ và các tài nguyên khác không cần sử dụng) và tốt cho sự ổn định của ứng dụng (nghĩa là đảm bảo ứng dụng được khởi động lại định kỳ khi có thể là mạng an toàn chống rò rỉ bộ nhớ và bộ nhớ thấp khác các vấn đề).
Điều này có thể (mặc dù có lẽ không nên, xem bên dưới :-) đạt được với một cái gì đó như:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (/* logged out */) {
exit(0);
} else {
// normal handling.
}
}
Vì ứng dụng sẽ thoát khỏi nền nó sẽ không nhìn nhầm với người dùng và sẽ không giống với sự cố, cung cấp giao diện người dùng được khôi phục vào lần tiếp theo họ chạy ứng dụng. Nói cách khác, đối với người dùng, nó sẽ trông không khác gì một hệ thống chấm dứt ứng dụng bắt đầu khi ứng dụng ở chế độ nền.
Tuy nhiên, tốt hơn là nên sử dụng một cách tiếp cận tiêu chuẩn hơn để cho hệ thống biết rằng ứng dụng có thể bị chấm dứt. Ví dụ: trong trường hợp này, bằng cách đảm bảo GPS không được sử dụng bằng cách dừng yêu cầu cập nhật vị trí, bao gồm tắt hiển thị vị trí hiện tại trên chế độ xem bản đồ nếu có. Bằng cách đó, hệ thống sẽ xử lý chấm dứt ứng dụng một vài phút (tức là [[UIApplication sharedApplication] backgroundTimeRemaining]
) sau khi ứng dụng vào nền. Điều này sẽ nhận được tất cả các lợi ích tương tự mà không phải sử dụng mã để chấm dứt ứng dụng.
- (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.
}
}
Và tất nhiên, việc sử dụng exit(0)
sẽ không bao giờ phù hợp với ứng dụng sản xuất trung bình chạy ở nền trước, theo các câu trả lời khác tham khảo http://developer.apple.com/iphone/l Library / qa / qa2008 / qa1561.html