iOS 7 SDK: 如何使用后臺(tái)獲取(Background Fetch)

2013-12-16 10:32:22來(lái)源:看引擎作者:

本文主要教你如何使用iOS 7 SDK多任務(wù)處理API–Background Fetch。我們生活在一個(gè)社交化的世界中,大部分用戶都安裝了幾個(gè)社交類app,但是每次用戶打開(kāi)app,他們必須要等待app加載更新才能看到跟更多最新的內(nèi)容

本文主要教你如何使用iOS 7 SDK多任務(wù)處理API–Background Fetch。我們生活在一個(gè)社交化的世界中,大部分用戶都安裝了幾個(gè)社交類app,但是每次用戶打開(kāi)app,他們必須要等待app加載更新才能看到跟更多最新的內(nèi)容,對(duì)于越來(lái)越?jīng)]耐心的用戶來(lái)說(shuō)這一點(diǎn)無(wú)疑令人非常痛苦,F(xiàn)在,iOS 7的后臺(tái)獲。˙ackground Fetch)可以很好地解決這個(gè)問(wèn)題,在用戶打開(kāi)應(yīng)用之前,app就能自動(dòng)更新獲取內(nèi)容。

以檢測(cè)流量的app為例來(lái)說(shuō)明Background Fetch如何工作。如果你會(huì)在每天早上查看應(yīng)用,我們假設(shè)在8:20 AM,,你的iOS app必須在當(dāng)時(shí)獲得信息,F(xiàn)在如果操作系統(tǒng)知道你將會(huì)在8:20 AM左右使用app,那么它可以提前獲得數(shù)據(jù),從而提供更好的用戶體驗(yàn)。

關(guān)于iOS 7多任務(wù)執(zhí)行更全面的概覽可參看我們的主題“
iOS 7 SDK: Multitasking Enhancements”。以下我們將會(huì)以一個(gè)實(shí)例工程來(lái)演示如何使用后臺(tái)獲。˙ackground Fetch)。
1.項(xiàng)目安裝

第一步是創(chuàng)建一個(gè)iOS 7項(xiàng)目,并選擇單視圖app,接著添加一些有用的屬性:

@property (nonatomic) NSMutableArray *objects;
@property (nonatomic) NSArray *possibleTableData;
@property (nonatomic) int numberOfnewPosts;
@property (nonatomic) UIRefreshControl *refreshControl;
NSMutablearray對(duì)象將會(huì)被用來(lái)在TableView中保存對(duì)象列表。在這個(gè)教程中,你將不能調(diào)用任何服務(wù)來(lái)獲得數(shù)據(jù)。相反,你將使用possibleTableData數(shù)組,并隨機(jī)從中選擇幾個(gè)對(duì)象。整個(gè)numberOfnewPosts代表新發(fā)布的內(nèi)容–每次進(jìn)行請(qǐng)求或者接收后臺(tái)獲取時(shí)可用。refrestControl是一個(gè)在更新任務(wù)時(shí)使用的控件。由于不在教程之內(nèi),所以本文不會(huì)在此展開(kāi)。

在Main.storyboard中,把ViewController改為UITableViewController,下一步,點(diǎn)擊UITableViewController,轉(zhuǎn)到Editor > Embed in > Navigation Controller。記得把自定義類設(shè)置為ViewController。然后轉(zhuǎn)至ViewController.m,第一步加載一些數(shù)據(jù)。以下代碼將會(huì)申請(qǐng)內(nèi)存并創(chuàng)建數(shù)據(jù)對(duì)象,創(chuàng)建一個(gè)標(biāo)題以及初始化refreshControl:

self.possibleTableData = [NSArray arrayWithObjects:@"Spicy garlic Lime Chicken",@"Apple Crisp II",@"Eggplant Parmesan II",@"Pumpkin Ginger Cupcakes",@"Easy Lasagna", @"Puttanesca", @"Alfredo Sauce", nil];
self.navigationItem.title = @"Delicious Dishes";
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(insertNewObject:) forControlEvents:UIControlEventValueChanged];
[self.tableView addSubview:self.refreshControl];
以上代碼將會(huì)產(chǎn)生一個(gè)提醒,因?yàn)槲覀儊G失了insertNewObject method。讓我們來(lái)解決它。該方法將會(huì)產(chǎn)生一個(gè)隨機(jī)數(shù),并且將從日期數(shù)組獲得對(duì)象相同的數(shù)據(jù),然后它將會(huì)通過(guò)新值來(lái)更新tableview。

- (void)insertNewObject:(id)sender
{
    self.numberOfnewPosts = [self getRandomNumberBetween:0 to:4];
    NSLog(@"%d new fetched objects",self.numberOfnewPosts);
    for(int i = 0; i < self.numberOfnewPosts; i++){
        int addPost = [self getRandomNumberBetween:0 to:(int)([self.possibleTableData count]-1)];
        [self insertObject:[self.possibleTableData objectAtIndex:addPost]];
    }
    [self.refreshControl endRefreshing];
}
當(dāng)你添加以下方法時(shí),getRandomNumberBetween提醒將會(huì)被禁止:

-(int)getRandomNumberBetween:(int)from to:(int)to {
    return (int)from + arc4random() % (to-from+1);
}
為了在 NSArray object上加載對(duì)象,我們需要執(zhí)行TableView委托函數(shù)。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = self.objects[indexPath.row];
    if(indexPath.row < self.numberOfnewPosts){
        cell.backgroundColor = [UIColor yellowColor];
    }
    else
        cell.backgroundColor = [UIColor whiteColor];
    return cell;
}
非常簡(jiǎn)單吧?如果運(yùn)行項(xiàng)目,你會(huì)看到一個(gè)類似下圖的界面:

2. Background Fetch

現(xiàn)在開(kāi)始創(chuàng)建Background Fetch功能,首先從Project開(kāi)始,接著是Capabilities,然后Put Background Modes ON,再選擇Background Fetch,如下圖所示:

但僅僅做這個(gè)是不夠的。默認(rèn)地,app不會(huì)調(diào)用后臺(tái)API,所以你需要在AppDelegate.m文件中把以下代碼添加至-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method.

[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
這個(gè)可以讓系統(tǒng)決定何時(shí)應(yīng)該展示新內(nèi)容,F(xiàn)在你的app已經(jīng)知道啟動(dòng)ackground fetch,讓我們告訴它要做些什么。方法-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler將會(huì)對(duì)你有所幫助。每當(dāng)執(zhí)行后臺(tái)獲取時(shí)該方法都會(huì)被調(diào)用,并且應(yīng)該被包含在AppDelegate.m文件中。以下是完整版本:

 
 
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    UINavigationController *navigationController = (UINavigationController*)self.window.rootViewController;
    id topViewController = navigationController.topViewController;
    if ([topViewController isKindOfClass:[ViewController class]]) {
        [(ViewController*)topViewController insertNewObjectForFetchWithCompletionHandler:completionHandler];
    } else {
        NSLog(@"Not the right class %@.", [topViewController class]);
        completionHandler(UIBackgroundFetchResultFailed);
    }
}
下一步你應(yīng)該也把ViewController頭文件放進(jìn)AppDelegate.m類。

 #import "ViewController.h"
注意insertNewObjectForFetchWithCompletionHandler并沒(méi)有被創(chuàng)建,所以還需要在ViewController.h中聲明它。

 - (void)insertNewObjectForFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler; 
現(xiàn)在關(guān)注執(zhí)行文件,類似于之前insertNewObject調(diào)用的添加。我們使用completionHandler來(lái)和系統(tǒng)“交流”,并讓它告訴我們app是否現(xiàn)在獲取數(shù)據(jù),或者當(dāng)前是否有有效數(shù)據(jù)。

- (void)insertNewObjectForFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    NSLog(@"Update the tableview.");
    self.numberOfnewPosts = [self getRandomNumberBetween:0 to:4];
    NSLog(@"%d new fetched objects",self.numberOfnewPosts);
    for(int i = 0; i < self.numberOfnewPosts; i++){
        int addPost = [self getRandomNumberBetween:0 to:(int)([self.possibleTableData count]-1)];
        [self insertObject:[self.possibleTableData objectAtIndex:addPost]];
    }
    /*
     At the end of the fetch, invoke the completion handler.
     */
    completionHandler(UIBackgroundFetchResultNewData);
}
完成代碼,現(xiàn)在我們模擬一個(gè)測(cè)試,并驗(yàn)證所有項(xiàng)目都能啟動(dòng)和運(yùn)行。

3. Simulated Background Fetch

如果想確定是否每件事都已經(jīng)配置好了,你需要編輯Schemes,在Schemes列表點(diǎn)擊Manage Schemes選項(xiàng),如下:

在Schemes管理區(qū)你可以復(fù)制app的scheme:

復(fù)制后scheme會(huì)在新窗口展示。你可在Options標(biāo)簽下更改它的名稱。選擇“Launch due to a background fetch event”框,并在所有窗口中點(diǎn)擊“OK”。

接著,使用復(fù)制的scheme運(yùn)行app。注意app不會(huì)在前臺(tái)打開(kāi),但是它應(yīng)該已經(jīng)獲得了一些內(nèi)容。如果打開(kāi)app,并且?guī)讉(gè)recipe已生效,那就說(shuō)明操作已經(jīng)成功了。為了使用后臺(tái)獲取功能,你也可以從Xcode菜單的Debug > Simulate Background Fetch開(kāi)始。

關(guān)鍵詞:iOS