[Objective-C] バックグラウンドで継続して処理を実行する

  • 57
    Like
  • 0
    Comment
More than 1 year has passed since last update.

通常、iOSアプリはバックグラウンドに回ったタイミングで処理が停止します。
これはバッテリーを長持ちさせるためにも必要な処置です。
しかしアプリによっては現在処理しているものが停止させられると困る場合があります。
(例えばなにかのダウンロード中は継続してダウンロードを終えるまで処理したほうがいいなど)

その場合に使えるのが、iOS4から実装されたマルチタスキングの機能です。
それを実現するためにはシステムに、「継続して処理を続けること」を伝えないとなりません。
そのためのメソッドがUIApplication#beginBackgroundTaskWithExpirationHandler:UIApplication#beginBackgroundTaskWithName:expirationHandler:です。

ドキュメントはこちら

サンプルコード

起動したらずっとNSLogで値を出力するだけのサンプルです。
これを実行することでバックグラウンドに移行してもログが出力され続けるのが確認できます。
(通常だとバックグラウンドに移行した時点でログ出力は止まる)

ちなみにバックグラウンドに移行するタイミングで処理を開始、とかではなくて通常行っていた処理がそのまま継続します。

なお、セットで実行することとしては、フォアグラウンドに戻ってきた際に[UIApplication.sharedApplication endBackgroundTask:self.bgid]を実行してバックグラウンドタスクを終了する必要があります。
self.bgidUIBackgroundTaskIdentifier型のID)


#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) UIBackgroundTaskIdentifier bgid;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [NSNotificationCenter.defaultCenter addObserver:self
                                           selector:@selector(willResignActive:)
                                               name:UIApplicationWillResignActiveNotification
                                             object:nil];
    [NSNotificationCenter.defaultCenter addObserver:self
                                           selector:@selector(didBecomeActive:)
                                               name:UIApplicationDidBecomeActiveNotification
                                             object:nil];

    [self update];
}

- (void)update
{
    if (self.timer) {
        [self.timer invalidate];
        self.timer = nil;
    }
    self.timer = [NSTimer scheduledTimerWithTimeInterval:3
                                                  target:self
                                                selector:@selector(update)
                                                userInfo:nil
                                                 repeats:YES];

    NSLog(@"timer");
}

- (void)willResignActive:(NSNotification *)notification
{
    NSLog(@"resign");

    UIApplication *app = UIApplication.sharedApplication;
    self.bgid = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:self.bgid];
        self.bgid = UIBackgroundTaskInvalid;
    }];
}

- (void)didBecomeActive:(NSNotification *)notification
{
    NSLog(@"become");

    [UIApplication.sharedApplication endBackgroundTask:self.bgid];
}

@end