19

I'm trying to programmatically return to the home screen in an iOS8 App using Swift. I want to continue the application running in the background though. Any ideas on how to do this?

Thanks in advance for the help.

Dave Tsay
  • 409
  • 1
  • 6
  • 14
  • 5
    In terms of programmatically sending the app into the background and returning to the home screen, you don't. See http://stackoverflow.com/q/5360846/1271826. In terms of keeping the app running in the background, there are different ways to achieve this depending upon what the app is doing in the background. See [App Programming Guide for iOS: Background Execution](https://developer.apple.com/library/ios/documentation/iphone/conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW1). – Rob Oct 22 '14 at 15:33
  • 3
    Also be ware that the only way now to return to the "home screen" is kill your app. Apple will see this a a crash and reject your app. – rckoenes Oct 22 '14 at 16:05
  • this is too bad - thanks for the answers – Dave Tsay Oct 26 '14 at 16:22

6 Answers6

35

When an app is launched, the system calls the UIApplicationMain function; among its other tasks, this function creates a singleton UIApplication object. Thereafter you access the object by calling the sharedApplication class method.

To exit gracefully (the iOS developer library explicitly warns you not to use exit(0) because this is logged as a crash ) you can use:

UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)

For example, my app exits when the user shakes the device. So, in ViewController.swift:

override func motionEnded(motion: UIEventSubtype,
    withEvent event: UIEvent?) {

        if motion == .MotionShake{

            //Comment: to terminate app, do not use exit(0) bc that is logged as a crash.

            UIControl().sendAction(Selector("suspend"), to: UIApplication.sharedApplication(), forEvent: nil)
        }}
Machado
  • 14,105
  • 13
  • 56
  • 97
reinaH
  • 534
  • 6
  • 10
  • 2
    xcode 7.3.1 auto suggests to change 'Selector("suspend")' to '#selector(NSURLSessionTask.suspend)'. Seems to work. I'm not sure how to check if there is a crash in the simulator. – rockhammer Jun 21 '16 at 04:01
  • Actually I can verify that it does work. In the stopwatch app I'm building, reinaH's code successfully hides the app when the stopwatch is keeping time and when it is lapped. Double-tapping the home button to recall the app shows the app has continued to keep time properly. – rockhammer Jun 21 '16 at 04:13
  • 1
    Update to Swift 3 UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil) – Qadir Hussain Dec 05 '16 at 12:26
  • this solution is just hide the application and when you try to open it again it will become alive from the saved state /last screen you was displayed – Amr Angry Feb 14 '17 at 14:50
  • This solution will not help if some situations that you need to force the app to kill (like change application language).Is there any solution for that scenario? – vivek agravat Mar 01 '17 at 09:29
  • 3
    xcode 9.0, Swift 4: UIControl().sendAction(#selector(NSXPCConnection.suspend), to: UIApplication.shared, for: nil) – DmitryKanunnikoff Nov 23 '17 at 21:04
31

Swift 4:

UIControl().sendAction(#selector(NSXPCConnection.suspend),
                       to: UIApplication.shared, for: nil)

Edit: It's worth mentioning that in iOS 12 there's a bug that will prevent network connectivity if the app is brought back from background after sending the suspend action.

Aviran
  • 5,160
  • 7
  • 44
  • 76
  • This is excellent, although looks kinda hackish. Works like on android when you call `finish()`, which closes the main activity but it is still available from memory should you choose to go back in. – OzzyTheGiant Oct 19 '19 at 20:10
8

For that you should use following code

import Darwin
exit(0)
Sergey Grischyov
  • 11,995
  • 20
  • 81
  • 120
  • 1
    This would be considered as a crash and might lead an app getting rejected from Apple –  May 23 '18 at 12:20
2

To force your app into the background, you can legally launch another app, such as Safari, via a URL, into the foreground.

See: how to open an URL in Swift3

UIApplication.shared.open() (and the older openURL) are a documented public APIs.

If you set the exits-on-suspend plist key, opening another app via URL will also kill your app. The use of this key is a documented legal use of app plist keys, available for any app to "legally" use.

Also, if your app, for some impolite reason, continues to allocate and dirty large amounts of memory in the background, without responding to memory warnings, the OS will very likely kill it.

Community
  • 1
  • 1
hotpaw2
  • 70,107
  • 14
  • 90
  • 153
0

How about setting of info.plist?

You can set "Application does not run in background" true in info.plist with editor.

Or Add this lines with code editor.

    <key>UIApplicationExitsOnSuspend</key>
    <true/>
UdevApp
  • 31
  • 5
-1

There is no way to "programmatically return to the home screen" except for crashing, exiting your program or calling unofficial API. Neither is welcome by Apple. Plus the Human Interface Guidelines are also covering this.

Update:

Maybe Apple has a different stance on this now, but the downvotes don't make it less true for iOS8. Here someone even quoted Apple on this: https://stackoverflow.com/a/5362887/33165

Also see the now outdated Technical Q&A from Apple

tcurdt
  • 14,518
  • 10
  • 57
  • 72