iOS开发Swift

Swift – 让程序挂起后,能在后台继续运行任务

1,程序的挂起和退出

由于iOS设备资源有限。当用户点击了home键,或者另一个应用程序启动了。那么原先那个程序便进入后台被挂起,不是退出,只是停止执行代码,同时它的内存被锁定。当应用程序恢复时,它会从停止的位置重新开始。

2,如下特殊的应用程序可以在后台长时间的运行

  • (1)在后台播放音频的应用程序可以在任意长的时间内保持活动状态,直到用户开始从另一个App播放音乐为止。
  • (2)在后台跟踪用户位置的应用程序可以运行任意长的时间。
  • (3)诸如Skype之类的网络协议电话(VoIP)应用程序可以定期运行,以向服务器签到,但除非正在进行通话,否则不允许不加限制地运行。

3,申请程序在后台短时运行

  • (1)除了上述的特殊应用,App进入后台时便自动挂起。但我们可以申请该应用在后台能短时间运行。但这个时长不能超过10分钟。
  • (2)后台短时运行的存在是为了让应用程序能够完成一个需要长时间运行的过程。比如将大型文件写会磁盘,完成下载,或者像即时通讯软件给对方发照片(选择发送后,即使进入后台,也能继续发送)。
  • (3)在10分钟结束时,应用程序必须告诉OS,它已经完成或者被终止。
  • (4)注意:并不能保证用于后台任务的额外时间是连续的,这些时间可能会被分为很多段,以延长电池寿命。

4,通过样例演示如何在后台运行任务

主页面上通过定时器不断的打印出数字。还有个开关按钮,切换选择程序进入后台后是否继续运行。开关开启时,按home键退出应用,过一会儿再回来,可以发现数字在后台还会一直打印数字。开关关闭,程序进入后台即挂起,不会再打印数字。

(这个需要使用真机测试,模拟器比较特殊,不管什么情况程序进入后台都会一直运行)

— ViewController.swift —

import UIKit
 
class ViewController: UIViewController {
     
    @IBOutlet weak var textView: UITextView!
     
    @IBOutlet weak var mySwitch: UISwitch!
     
    var i=0
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //创建定时任务
        _ = NSTimer.scheduledTimerWithTimeInterval(1,
            target:self,selector:Selector("tickDown"),
            userInfo:nil,repeats:true)
    }
     
    //计时器每秒触发事件
    func tickDown() {
        textView.text! += "\(i++) "
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

— AppDelegate.swift —

import UIKit
 
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
 
    var window: UIWindow?
     
    //后台任务
    var backgroundTask:UIBackgroundTaskIdentifier! = nil
 
 
    func application(application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        return true
    }
 
    func applicationWillResignActive(application: UIApplication) {
    }
 
    func applicationDidEnterBackground(application: UIApplication) {
        let controller:ViewController = self.window?.rootViewController as! ViewController
        controller.textView.text! += "进入后台 "
         
        //如果已存在后台任务,先将其设为完成
        if self.backgroundTask != nil {
            application.endBackgroundTask(self.backgroundTask)
            self.backgroundTask = UIBackgroundTaskInvalid
        }
         
        //如果要后台运行
        if controller.mySwitch.on {
            //注册后台任务
            self.backgroundTask = application.beginBackgroundTaskWithExpirationHandler({
                () -> Void in
                //如果没有调用endBackgroundTask,时间耗尽时应用程序将被终止
                application.endBackgroundTask(self.backgroundTask)
                self.backgroundTask = UIBackgroundTaskInvalid
            })
        }
    }
 
    func applicationWillEnterForeground(application: UIApplication) {
    }
 
    func applicationDidBecomeActive(application: UIApplication) {
    }
 
    func applicationWillTerminate(application: UIApplication) {
    }
}