Adding Background Fetch Capabilities to Your Apps(在後臺獲取數據)

  與前一篇介紹app(主動)在後臺運行長時間的任務不同,這次是app(被動)讓IOS喚醒啓動模式

  一般情況,都是打開運行app,然後讓app刷新,才能看到新內容,但是這種新的喚醒機制是讓app在後臺就完成刷新任務,當用戶打開app時,新內容已經呈現出

  前提:項目設置-Capabilities-Background Modes:Background fetch 勾選中

  方法:

      //設置喚醒時間

     - (void)setMinimumBackgroundFetchInterval:(NSTimeInterval)minimumBackgroundFetchInterval

      //執行後臺獲取數據操作

     - (void)application:(UIApplication *)application 

                   performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler

e.g.

 AppDelegate.h

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;

@property (nonatomic, strong) NSMutableArray *allNewsItems;

@end


 AppDelegate.m

#import "AppDelegate.h"

#import "NewsItem.h" //自定義對象NewsItem 有兩屬性 NSDate *date , NSString *text;

@implementation AppDelegate

//初始化數組

- (NSMutableArray *) allNewsItems{

    if (_allNewsItems == nil){

        _allNewsItems = [[NSMutableArray alloc] init];      

        /* Pre-populate the array with one item */

        NewsItem *item = [[NewsItem alloc] init];

        item.date = [NSDate date];

        item.text = [NSString stringWithFormat:@"News text 1"];

        [_allNewsItems addObject:item];       

    }

    return _allNewsItems;

}

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

    //設置喚醒時間,默認UIApplicationBackgroundFetchIntervalNever,稍後要執行performFetchWithCompletionHandler

    [application setMinimumBackgroundFetchInterval: UIApplicationBackgroundFetchIntervalMinimum];   

    return YES;

}

// 後臺獲取數據

- (void) application:(UIApplication *)application

  performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))

    completionHandler{   

    BOOL haveNewContent = NO;

    [self fetchNewsItems:&haveNewContent];  

    if (haveNewContent){

        completionHandler(UIBackgroundFetchResultNewData); // 成功獲取到新數據

    } else {              // UIBackgroundFetchResultFailed 失敗

        completionHandler(UIBackgroundFetchResultNoData); // 沒有新數據

    }  

}

//參數BOOL帶*,表示作爲地址存值 

//模擬從服務器獲取數據,若是0則無數據,1爲有數據

- (void) fetchNewsItems:(BOOL *)paramFetchedNewItems{    

    if (arc4random_uniform(2) != 1){  //arc4random_uniform(n): [0,n) 隨機數

        if (paramFetchedNewItems != nil){

            *paramFetchedNewItems = NO;

        }

        return;

    }   

    [self  willChangeValueForKey:@"allNewsItems"]; //KVO模式 willChangeValueForKey -> didChangeValueForKey

    NewsItem *item = [[NewsItem alloc] init];

    item.date = [NSDate date];

    item.text = [NSString stringWithFormat:@"News text %lu",

                 (unsigned long)self.allNewsItems.count + 1];

    [self.allNewsItems addObject:item];    

    if (paramFetchedNewItems != nil){

        *paramFetchedNewItems = YES;

    }    

    [self  didChangeValueForKey:@"allNewsItems"];   

}

.....

@end


  啓動界面 -TableViewController.h

@interface TableViewController : UITableViewController

@end


  -TableViewController.m

#import "TableViewController.h"

#import "AppDelegate.h"

#import "NewsItem.h"

@interface TableViewController ()

@property (nonatomic, weak) NSArray *allNewsItems; //注意,這裏是用weak

@property (nonatomic, assign) BOOL mustReloadView;

@end

@implementation TableViewController

- (void)viewDidLoad

{

    [super viewDidLoad];   

    AppDelegate *appDelegate = [UIApplication  sharedApplication].delegate;

    self.allNewsItems = appDelegate.allNewsItems;  //因爲是weak,所以若appDelegate.allNewsItems後續指向空時,self.allNewsItems也隨之

    //註冊以接收KVO通知   

    [appDelegate addObserver:self

                  forKeyPath:@"allNewsItems"

                     options:NSKeyValueObservingOptionNew

                     context:NULL];    

    [[NSNotificationCenter defaultCenter] addObserver:self

                                             selector:@selector(handleAppIsBroughtToForeground:)

                                                 name:UIApplicationWillEnterForegroundNotification

                                               object:nil];

}

//當keyPath對應的值改變時。。必須先註冊(addObserver:forKeyPath:options:context)

//在AppDelegate.m文件中fetchNewsItems時,有didChangeValueForKey,所以在值改變時此處會執行

- (void) observeValueForKeyPath:(NSString *)keyPath

                       ofObject:(id)object

                         change:(NSDictionary *)change

                        context:(void *)context{    

    if ([keyPath isEqualToString:@"allNewsItems"]){

        if ([self isBeingPresented]){

            [self.tableView reloadData];

        } else {

            self.mustReloadView = YES;

        }

    }   

}

- (void) handleAppIsBroughtToForeground:(NSNotification *)paramNotification{

    if (self.mustReloadView){

        self.mustReloadView = NO;

        [self.tableView reloadData];

    }

}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.allNewsItems.count;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    

    static NSString *CellIdentifier = @"Cell";    

    UITableViewCell *cell = [tableView

                             dequeueReusableCellWithIdentifier:CellIdentifier

                             forIndexPath:indexPath];    

    NewsItem *newsItem = self.allNewsItems[indexPath.row];   

    cell.textLabel.text = newsItem.text;   

    return cell;

}

//取消相關注冊

- (void) dealloc{

    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;

    [appDelegate removeObserver:self forKeyPath:@"allNewsItems"];

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

@end




發佈了15 篇原創文章 · 獲贊 0 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章