Help us understand the problem. What is going on with this article?

[Swift]バックグラウンドでも処理を続ける方法

More than 3 years have passed since last update.

アプリの処理をバックグラウンドにいっても続ける必要があったので、メモをします。

実行環境

  • OS X El Capitan‎
  • Xcode 7.3
  • Swift 2.2
  • iPhone 6Plus (iOS9.2)

UIBackgroundTaskIdentifierの登録

通常、NSTimerなどの継続して動く処理でもアプリバックグラウンドに移動した瞬間に処理が止まってしまいます。
しかし、UIApplication- beginBackgroundTaskWithName:expirationHandler:- beginBackgroundTaskWithExpirationHandler:を実行するとバックグラウンド状態でも処理を継続することができます。

iOS4から実装されたマルチタスキングの機能なのだそうです。

ViewControllerに一秒ごとに現在時刻をプリントする処理を書いてみます。

ViewController.swift
import UIKit

class ViewController: UIViewController {

    var timer = NSTimer()

    override func viewDidLoad() {
        super.viewDidLoad()

        //バックグラウンドでも実行したい処理
        updating()
    }
    func updating()  {
        if self.timer.valid {
            self.timer.invalidate()
        }

        self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(updating), userInfo: nil, repeats: true)

        print("updating_now_time:" + NSDate().description)
    }
}


このままでは、アプリがバックグラウンド状態になったら、現在時刻のプリントは止まってしまいます。

AppDelegate.swiftで処理を継続する処理を追加したいと思います

AppDelegate.swift
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var backgroundTaskID : UIBackgroundTaskIdentifier = 0

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.

        return true
    }

    //バックグラウンド遷移移行直前に呼ばれる
    func applicationWillResignActive(application: UIApplication) {

        self.backgroundTaskID = application.beginBackgroundTaskWithExpirationHandler(){
            [weak self] in
            application.endBackgroundTask((self?.backgroundTaskID)!)
            self?.backgroundTaskID = UIBackgroundTaskInvalid
        }

    }

    //アプリがアクティブになる度に呼ばれる
    func applicationDidBecomeActive(application: UIApplication) {

        application.endBackgroundTask(self.backgroundTaskID)
    }

}

解説

var backgroundTaskID : UIBackgroundTaskIdentifier = 0

UIBackgroundTaskIdentifier型の変数を保持型プロパティとして定義します。
レファレンスUIApplication Class Referenceを見る限り、UIBackgroundTaskIdentifier型はInt型のタイプエイリアスみたいです。

typealias UIBackgroundTaskIdentifier = Int

とりあえず値を0としておきました。なんでも良さそうです。

次に、バックグラウンド状態になる直前に呼ばれる- applicationWillResignActive:メソッドでbackgroundTaskIDプロパティを登録します

    //バックグラウンド遷移移行直前に呼ばれる
    func applicationWillResignActive(application: UIApplication) {

        self.backgroundTaskID = application.beginBackgroundTaskWithExpirationHandler(){
            [weak self] in
            application.endBackgroundTask((self?.backgroundTaskID)!)
            self?.backgroundTaskID = UIBackgroundTaskInvalid
        }

    }

バックグラウンドタスクはフォアグラウンドに戻った時には– endBackgroundTask:メソッドを実行して、タスクの終了を知らせないといけないそうです。フォアグラウンドに戻った際に呼ばれるメソッドは- applicationDidBecomeActive:なのでそこで実装します。

    //アプリがアクティブになる度に呼ばれる
    func applicationDidBecomeActive(application: UIApplication) {

        application.endBackgroundTask(self.backgroundTaskID)
    }

 まとめ

これでバックグラウンドでもNSTimerの処理が継続されるはずです。
ただ、試したところシミュレーターではUIBackgroundTaskIdentifierの登録をしなくてもバックグラウンドで処理が継続していました。。
なんでだろう。。

とりあえず、実機ではUIBackgroundTaskIdentifierの登録が必要なのでご参考になれば幸いです!

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした