iPhone 앱을 프로그래밍 중이며 특정 사용자 작업으로 인해 강제로 종료해야합니다. 앱이 할당 한 메모리를 정리 한 후 애플리케이션을 종료하기 위해 호출하는 적절한 방법은 무엇입니까?
iPhone 앱을 프로그래밍 중이며 특정 사용자 작업으로 인해 강제로 종료해야합니다. 앱이 할당 한 메모리를 정리 한 후 애플리케이션을 종료하기 위해 호출하는 적절한 방법은 무엇입니까?
답변:
시도 했습니까 exit(0)
?
또는 [[NSThread mainThread] exit]
시도하지 않았지만 더 적절한 솔루션처럼 보입니다.
iPhone에는 앱을 종료한다는 개념이 없습니다. 앱을 종료시키는 유일한 조치는 휴대 전화의 홈 버튼을 터치하는 것 뿐이며 개발자가 액세스 할 수있는 것은 아닙니다.
Apple에 따르면 앱이 자체적으로 종료되지 않아야합니다. 사용자가 홈 버튼을 누르지 않았으므로 홈 화면으로 돌아 가면 앱이 다운되었다는 느낌을 사용자에게 제공합니다. 혼란스럽고 비표준적인 동작이므로 피해야합니다.
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);
}
}
exit(0)
은 중요하지 않습니다. 포인트는 응용 프로그램이 "종료 행동"을 가지고 있습니다. 매우 중요한 제삼자가 만든 일부 앱을 제외하고 AppStore에서 종료 동작 자체는 금지됩니다. 또한 홈 버튼 동작 모방도 거부 될 수 있습니다.
여기서 Q & A를 확인하십시오 : https://developer.apple.com/library/content/qa/qa1561/_index.html
Q : 프로그래밍 방식으로 iOS 응용 프로그램을 종료하려면 어떻게합니까?
iOS 애플리케이션을 정상적으로 종료하기 위해 제공되는 API는 없습니다.
iOS에서 사용자는 홈 버튼을 눌러 애플리케이션을 닫습니다. 응용 프로그램에 의도 한 기능을 제공 할 수없는 조건이있는 경우 권장되는 접근 방식은 문제의 특성과 사용자가 취할 수있는 조치 (WiFi 켜기, 위치 서비스 활성화 등)를 나타내는 경고를 사용자에게 표시하는 것입니다. 사용자가 자신의 재량에 따라 응용 프로그램을 종료 할 수 있도록합니다.
경고 :
exit
기능을 호출하지 마십시오 . 응용 프로그램 호출exit
은 정상적으로 종료되고 홈 화면으로 애니메이션되지 않고 사용자에게 충돌 한 것으로 나타납니다.또한 exit를 호출하면
-applicationWillTerminate:
유사한UIApplicationDelegate
메소드가 호출되지 않으므로 데이터가 저장 되지 않을 수 있습니다.개발 또는 테스트 중에 응용 프로그램, 종료
abort
기능 또는assert
매크로 를 종료 해야하는 경우
실제로 프로그램을 종료하는 방법이 아니라 사람들을 강제로 종료하는 방법입니다.
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];
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);
모든 작업이 수행됩니다. 그리고 가장 좋은 점은 종료하려는 사용자의 의도입니다. 이것이 호출하는 데 문제가되지 않는 이유입니다.
내 오디오 앱에서 음악이 계속 재생되는 동안 사람들이 기기를 동기화 한 후에 앱을 종료해야했습니다. 동기화가 완료되는 즉시 알림을받습니다. 그러나 그 직후 앱을 종료하면 실제로 충돌처럼 보입니다.
대신 다음 배경 작업에서 앱을 완전히 종료하도록 플래그를 설정했습니다. 동기화 후 앱을 새로 고침해도 괜찮습니다.
내 앱이 최근에 거부되었으므로 문서화되지 않은 방법을 사용했습니다. 말 그대로 :
"안타깝게도 개인 API를 사용하고 있기 때문에 App Store에 추가 할 수 없습니다. iPhone 개발자 프로그램 사용권 계약 섹션 3.3.1에 설명 된 비공개 API 사용은 금지됩니다.
"3.3.1 응용 프로그램은 Apple에서 규정 한 방식으로 문서화 된 API 만 사용할 수 있으며 개인 API를 사용하거나 호출해서는 안됩니다."
애플리케이션에 포함 된 비공개 API는 terminateWithSuccess "입니다.
애플의 말 :
"경고 : 이탈 기능을 호출하지 마십시오. 이탈을 호출하는 응용 프로그램은 정상적으로 종료하고 홈 화면으로 애니메이션하는 대신 충돌이 발생한 것으로 나타납니다."
나는 이것이 나쁜 가정이라고 생각합니다. 사용자가 종료 버튼을 누르면 "응용 프로그램이 이제 종료됩니다."와 같은 메시지가 나타나면 충돌이 발생하지 않습니다. Apple은 응용 프로그램을 종료하는 올바른 방법을 제공해야합니다 (exit (0) 아님).
이것은 좋은 대답을 얻었지만 조금 확장하기로 결정했습니다.
Apple의 iOS 휴먼 인터페이스 지침을 잘 읽지 않으면 애플리케이션을 AppStore에 승인 할 수 없습니다. (그들은 일을 당신을 거부 할 수있는 권리 보유 아무것도 는 '음주 프로그래밍을 종료하지 "그들에 대하여) http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices을. html 은이 경우 어떻게 취급해야하는지에 대한 정확한 지침입니다.
Apple 플랫폼에 문제가있는 경우 쉽게 해결책을 찾을 수 없으면 HIG에 문의하십시오. Apple은 단순히 당신이 그것을 원하지 않기 때문에 가능합니다. 그들은 일반적으로 (애플이 아니므로 항상 보장 할 수는 없습니다) 그들의 문서에서 그렇게 말하십시오.
응용 프로그램에 인터넷 연결이 필요한 경우 응용 프로그램을 '종료'해야 할 수 있습니다. 경고를 표시 한 후 다음과 같이 할 수 있습니다.
if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
[[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
kill(getpid(), SIGINT);
}
Apple은 이러한 기능의 사용을 강력히 권장하지 않으므로 exit(0)
, abort()
함수를 사용하여 앱을 종료 할 수 없습니다 . 개발 또는 테스트 목적으로이 기능을 사용할 수 있습니다.
개발 또는 테스트 중에 응용 프로그램을 종료해야하는 경우 중단 기능 또는 매크로 확인이 권장됩니다.
자세한 정보를 얻으려면 이 Apple Q & A 스레드를 찾으십시오 .
이 기능을 사용하면 응용 프로그램이 충돌하는 것처럼 인상을 줄 수 있습니다. 그래서 특정 기능을 사용할 수 없기 때문에 앱 종료에 대해 사용자에게 알리는 종료 메시지와 함께 경고를 표시 할 수있는 제안이 있습니다.
그러나 앱 시작 및 중지에 대한 iOS 휴먼 인터페이스 지침은 응용 프로그램을 종료하기 위해 종료 또는 닫기 버튼 을 사용하지 말 것을 제안합니다 . 오히려 상황을 설명하기 위해 적절한 메시지를 표시하도록 제안하고 있습니다.
iOS 앱에는 닫기 또는 종료 옵션이 표시되지 않습니다. 사람들은 다른 앱으로 전환하거나 홈 화면으로 돌아가거나 기기를 절전 모드로 전환 할 때 앱 사용을 중지합니다.
프로그래밍 방식으로 iOS 앱을 종료하지 마십시오. 사람들은 이것을 충돌로 해석하는 경향이 있습니다. 앱이 의도 한대로 작동하지 못하는 상황이 발생하면 사용자에게 상황에 대해 알려주고 앱에서 수행 할 수있는 작업을 설명해야합니다.
- (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 new] addObject : nil] 접근 방식을 사용하여 tell-tale Exit (0) 함수 호출을하지 않고 앱을 강제 종료 (충돌)했습니다.
왜? 내 앱은 모든 네트워크 API 호출에서 인증서 고정을 사용하여 중간자 공격을 방지합니다. 여기에는 금융 앱이 시작될 때 초기화 호출이 포함됩니다.
인증서 인증이 실패하면 모든 초기화 호출에서 오류가 발생하고 내 앱이 불확실한 상태가됩니다. 앱이 OS에 의해 제거되지 않으면 여전히 초기화되지 않고 신뢰할 수 없으므로 사용자가 집으로 돌아간 다음 다시 앱으로 돌아 오게해도 도움이되지 않습니다.
따라서이 경우 앱이 안전하지 않은 환경에서 작동하고 있음을 알리는 경고를 표시 한 다음 "Close"를 누르면 위에서 언급 한 방법으로 앱을 강제 종료합니다.
[[UIApplication sharedApplication] terminateWithSuccess];
그것은 잘 작동하고 자동으로 전화
- (void)applicationWillTerminateUIApplication *)application delegate.
컴파일 시간 경고를 제거하려면이 코드를 추가하십시오.
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end
직접 함수를 호출해서는 안됩니다 exit(0)
응용 프로그램을 즉시 종료하고 앱이 다운 된 것처럼 보이기 때문에 를 . 따라서 사용자에게 확인 알림을 표시하고이를 직접 수행하는 것이 좋습니다.
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()
}
}
iPadOS 13에서는 이제 다음과 같이 모든 장면 세션을 닫을 수 있습니다.
for session in UIApplication.shared.openSessions {
UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
}
이것은 전화 할 것이다 applicationWillTerminate(_ application: UIApplication)
앱 위임 하고 결국 앱을 종료합니다.
그러나 다음 두 가지에주의하십시오.
모든 장면 을 닫는 데 사용되는 것은 아닙니다 . ( https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/multiple-windows/ 참조 )
iPhone의 iOS 13에서는 컴파일되고 제대로 실행되지만 아무것도하지 않는 것 같습니다.
iOS / iPadOS 13의 장면에 대한 추가 정보 : https://developer.apple.com/documentation/uikit/app_and_environment/scenes
백그라운드에서 실행되는 오래 지속되는 앱인 경우 (예 : 위치 업데이트 사용) 위치 업데이트를 사용하여 앱을 종료하는 것이 적절할 수 있습니다. 백그라운드 기능 .
예를 들어 사용자가 위치 기반 앱에서 로그 아웃하고 홈 버튼을 사용하여 앱을 백그라운드로 푸시한다고 가정합니다. 이 경우 앱이 계속 실행되지만 앱을 완전히 종료하는 것이 좋습니다. 그것은 사용자에게 좋을 것이고 (메모리 및 기타 리소스를 사용할 필요가 없음), 앱 안정성에 좋을 것입니다 (즉, 가능하면 메모리 누수 및 기타 메모리 부족에 대한 안전망이 앱을 주기적으로 다시 시작해야합니다) 문제).
이것은 (아마도 안됩니다 : 아래 참조 :-) 다음과 같은 방법으로 달성 할 수 있습니다 :
- (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.
}
}
물론 http://developer.apple.com/iphone/library/qa/qa2008/qa1561.htmlexit(0)
을 참조하는 다른 답변에 따르면 포 그라운드에서 실행되는 평균 프로덕션 앱 에는 사용 하지 않는 것이 좋습니다.