プログラマーだけん、がんばる

神の国、島根のプログラマー。サーバ、Rubyまわりの技術(Ruby on Rails, Rhodes etc..)やiOS, Androidなどの開発を行っていくうえで、役だったことなどを共有できればいいなと思います。

iOS7によるバックグラウンド処理 ~ 1.Backgroud Fetch編 ~

Background Fetchとは?

iOS7から新しく追加された、「Background Mode」の一つです。
では具体的にはどんなことができるのか?下記にまとめてみます。

  • iOS側が不定期に、対象のアプリを呼び起こす。

iOS側が不定期に、

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

というメソッドを呼び起こします。この時点で驚きです。非常に強力で賢い機能です。
しかし、なぜ不定期なのか?
それは、iOS側が日々のユーザのiPhone等の使用状況を学習して、バッテリー等の観点から適切なタイミングで呼び起こすからです。

  • メソッドを呼び起こす、最短のインターバルが指定出来ます。

いくら賢いタイミングで呼び出すとしても、結局のところ不定期ですので、困る場合があると思います。
その為、下記のメソッドの使用によって、最短のインターバルを設定出来ます。

setMinimumBackgroundFetchInterval:

実際にやってみよう

まず、以下のスクリーンショットのように、Xcodeでの設定が必要です。f:id:famtom:20131013100620p:plain

では次にAppDelegate.mを実装していきます。
まず、アプリケーション起動時に呼ばれる、

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

の中でBackgroundFetchの最短インターバルをセットします。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
    return YES;
}

ここでは「UIApplicationBackgroundFetchIntervalMinimum」という定数を指定しています。
これで、BackgroundFetchが呼び起こされます。
次に、呼び起こされるメソッドを定義します。

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    //ここから実際にバックグラウンドで行いたい処理
    // 通知を作成する
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    
    notification.fireDate = [[NSDate date] dateByAddingTimeInterval:1];
    notification.timeZone = [NSTimeZone defaultTimeZone];
    notification.alertBody = @"BackgroundFetch";
    notification.soundName = UILocalNotificationDefaultSoundName;
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    
    //バックグラウンド処理が成功した場合には下記のように
    //UIBackgroundFetchResultNewDataを引数にcompletionHandlerを呼ぶ(必須)
    //失敗した場合にはUIBackgroundFetchResultFailedを引数に渡す。
    completionHandler(UIBackgroundFetchResultNewData);
}

以上で終わりです。非常に簡単です。
これで、BackgroundFetchが発生した際に

  • (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

が呼ばれて、Notificationが表示されるはずです。

ここで注意して欲しいのが最後の一行です。

    completionHandler(UIBackgroundFetchResultNewData);

BackgroundFetchでは、処理が終了した後に、終了しということをiOS側へ通知するためにcompletionHandlerを必ず呼び出します。
引数に渡すの下記の二つのどちらかで、場合によって使い分けます。

UIBackgroundFetchResultNewData //成功時
UIBackgroundFetchResultFailed //失敗時

以上が簡単なBackgroundFetchの方法です。

実行

では実際に実行してみます。
BackgroundFetchはシミュレーター上で確認する事が出来ます。
まずはXcodeから「Run」を実行してシミュレーターを立ち上げます。
ここでは、Xcodeの機能をつかってBackgroundFetchを無理矢理呼び起こします。

Xcodeを選択して、上のOSのツールバーから、「Debug」-> 「Simulate Background Fetch」を選択します。
f:id:famtom:20131013104216p:plain

これで、シミュレーター上でBackgroundFetchが実行されます。
f:id:famtom:20131013104512p:plain

上にNotificationが表示され、無事バックグラウンドで処理が実行された事が分かります。
これがBackgroundFetchです。

最後に

今回作成したサンプルです #=> https://github.com/tomomura/ios-background-fetch-sample
非常に強力な機能なので、既にアプリを作っておられる方などは、BackgroundFetchを使用したいと思われる方が多いと思います。
ただ、iOS7で追加されたバックグラウンド処理はこれだけではありません。
他にも非常に強力なバックグラウンド処理が追加されています。
後々、このブログにもアップしていくので楽しみにしていて下さい。
ではでは。