当前位置: > > > Swift - 后台获取数据(Background Fetch)的实现

Swift - 后台获取数据(Background Fetch)的实现

前面讲了如何让程序申请后台短时运行。但这个额外延长的时间毕竟有限。所以从iOS7起又引入两种在后台运行任务的方式:后台获取和后台通知。

1,后台获取介绍
后台获取(Background Fetch)是为了那些需要定期更新的应用程序设计的,比如天气应用,新闻客户端,社交网络应用程序等。在启动后台获取之后,应用程序可以在后台被唤醒,在后台获取最新信息,以便在用户将应用程序转到前台时能够立即显示这些信息。

2,后台获取功能开启
首先在选中项目,在Capabilities(功能)选项卡,启用Background Modes(后台模式)中的Background Fetch(后台获取)


3,后台获取时间间隔设置
(1)开启后台获取功能后,还需要在代码中使用setMinimumBackgroundFetchInterval()方法设置最短唤醒程序的时间间隔(秒)。但具体什么时候程序会被唤醒获取数据,就不可控了。这个由系统自己决定。
(2)如果想要告诉尽可能频繁调用,就直接设成UIApplicationBackgroundFetchIntervalMinimum

4,使用样例
程序挂起后,自动从后台获取北京时间,获取后使用本地通知提醒用户。
(注意:后台获取执行后要调用completionHandler,告诉系统获取数据是否成功)
    
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    func application(application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            //开启通知
            let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],
                categories: nil)
            application.registerUserNotificationSettings(settings)
            return true
    }
    
    func applicationWillResignActive(application: UIApplication) {
    }
    
    func applicationDidEnterBackground(application: UIApplication) {
        //虽然定义了后台获取的最短时间,但iOS会自行以它认定的最佳时间来唤醒程序,这个我们无法控制
        //UIApplicationBackgroundFetchIntervalMinimum 尽可能频繁的调用我们的Fetch方法
        application.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
    }
    
    func applicationWillEnterForeground(application: UIApplication) {
    }
    
    func applicationDidBecomeActive(application: UIApplication) {
    }
    
    func applicationWillTerminate(application: UIApplication) {
    }
    
    //后台获取数据
    func application(application: UIApplication,
        performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
            //创建NSURL对象
            let url:NSURL! = NSURL(string:"http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json")
            //创建请求对象
            let request:NSURLRequest = NSURLRequest(URL: url)
            
            let session = NSURLSession.sharedSession()
            
            let dataTask = session.dataTaskWithRequest(request,
                completionHandler: {(data, response, error) -> Void in
                    if error != nil{
                        print(error?.code)
                        print(error?.description)
                        
                        //让OS知道获取数据失败
                        completionHandler(UIBackgroundFetchResult.Failed)
                    }else{
                        let str = NSString(data: data!, encoding: NSUTF8StringEncoding)
                        print(str)
                        //清除所有本地推送
                        //UIApplication.sharedApplication().cancelAllLocalNotifications()
                        //创建UILocalNotification来进行本地消息通知
                        let localNotification = UILocalNotification()
                        //推送时间(立刻推送)
                        localNotification.fireDate = NSDate(timeIntervalSinceNow: 0)
                        //时区
                        localNotification.timeZone = NSTimeZone.defaultTimeZone()
                        //推送内容
                        localNotification.alertBody = "获取时间成功:\(str)"
                        //声音
                        localNotification.soundName = UILocalNotificationDefaultSoundName
                        UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
                        
                        //让OS知道已经获取到新数据
                        completionHandler(UIBackgroundFetchResult.NewData)
                        //completionHandler(UIBackgroundFetchResult.NoData)
                    }
            }) as NSURLSessionTask
            
            //使用resume方法启动任务
            dataTask.resume()
    }
}

5,后台获取测试 
(1)模拟器测试的话,只要选择Xcode 菜单栏的 Debug下的 Simulate Background Fetch即可 
(2)真机调试,如果没有连着电脑有时候等了一天才发生后台获取。连着电脑可能等个几分钟就能获取。
评论2
  • 2楼
    2017-08-02 11:20
    ifelseboyxx

    站长 Background Fetch 这个功能打开能保持后台多久不被挂起啊?10分钟?还是不确定? 提交审核需要注意什么吗?会被拒吗?

    站长回复

    这个不是说让程序保持后台不会被挂起,而是程序即使被关闭以后,过段时间内也会后台获取数据,这样用户下次启动程序时,界面上已经是最新的数据了。

    但程序被关闭后要隔多长时间才会去获取数据,这个就看系统分配了。这个提交应该也没什么要特别注意的。
    如果你想要实现后台继续运行任务,可以参考我之前的另一篇文章:Swift - 让程序挂起后,能在后台继续运行任务

  • 1楼
    2017-04-17 14:51
    白色天空729

    站长 这个 真机测试 这个demo 没反应,还有 模拟器 好像得手动 到Xcode底下开启fetch data才收到数据,没办法 让他自动执行吗?

    站长回复

    这个具体执行时间由系统来决定,什么时候执行我们没法干预。使用真机有时等个一天可能也不执行。