Background Modes

Background Modes

内容来源自:Background Modes Tutorial: Getting Started

1.播放音频
在后台播放音频启用如下的设置:

在这里插入图片描述

2.定位更新

即使App在后台,也能收到定位更新的消息

如下的方式,创建CLLocationManager

  private lazy var locationManager: CLLocationManager = {
    let manager = CLLocationManager()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    //1. request authorization
    manager.requestAlwaysAuthorization()
    if #available(iOS 9, *) {
      manager.allowsBackgroundLocationUpdates = true
    }
    return manager
  }()

注意requestAlwaysAuthorization只在iOS8及以后版本有效

设置background modes

在这里插入图片描述

另外还要在Info.plist中添加key,解释为什么要使用定位:

  • Privacy — Location Always and When In Use Usage Description
  • Privacy — Location When In Use Usage Description

如果是在模拟器上跑的话,使用如下的设置来来模拟位置更新:

在这里插入图片描述

3.Finite-Length Tasks

从技术上来讲,Finite-Length Task并不是background mode,所以并不需要在Capabilities中进行设置。实际上,它是,当App在后台时,允许你在一段有限的时间内执行任何代码

对Finite-Length Tasks的理解,可参考:Executing a Finite-Length Task in the Background

如果你的app正在执行task中,并需要完成这个task,可通过调用UIApplication对象的beginBackgroundTaskWithName:expirationHandler: 或者 beginBackgroundTaskWithExpirationHandler:方法,来请求额外的执行时间。调用这些方法会暂时延迟app的暂停,给你一些时间来完成task。在完成后,需调用endBackgroundTask:方法来让系统知道task已完成,可以被suspended
每次调用beginBackgroundTaskWithName:expirationHandler:或者beginBackgroundTaskWithExpirationHandler:方法,都会生成一个唯一的token,与相应的task绑定在一起。当app完成了task,需调用endBackgroundTask:方法,带上生成的token,让系统知道task已完成。
如果在启动task的时候,你提供了一个 expiration handler,系统会调用这个handler,此时你有最后的一次机会来结束task
并不需要在app进入后台后才指定后台task。通常的做法是,在启动一个task之前,就调用beginBackgroundTaskWithName:expirationHandler:或者beginBackgroundTaskWithExpirationHandler:方法,在结束后调用 endBackgroundTask:方法

由iOS来决定app进入后台后你还有多少时间,并不能保证一定有多少时间,可通过检查UIApplication.sharedbackgroundTimeRemaining属性,来获取所剩的时间

The general, observation-based consensus is that you get three minutes
通常来说有3分钟

这个例子是计算斐波那契数列,并且可以在后台计算

func registerBackgroundTask() {
  backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
    self?.endBackgroundTask()
  }
  assert(backgroundTask != .invalid)
}
  
func endBackgroundTask() {
  print("Background task ended.")
  UIApplication.shared.endBackgroundTask(backgroundTask)
  backgroundTask = .invalid
}

4.Background Fetch

Background Fetch在iOS7中被引入。例如,要在app中实现一个动态消息的功能,在使用Background Fetch之前,你可能会在viewWillAppear(_:)方法中来获取新的数据。
这样做所带来的问题是,用户在最初的几秒看到的是旧数据,直到获取到新的数据。如果用户一打开app,就能展示新的数据,这样做岂不是更好?
当启用Background Fetch后,系统会决定启用Background Fetch的时机。例如,如果你的用户通常在9AM打开app,Background Fetch的时机非常有可能在这个时间之前。

设置Background Fetch

  • Capabilities中的Background Modes勾上Background fetch

    在这里插入图片描述

  • 使用setMinimumBackgroundFetchInterval(_:)方法设置时间间隔

  • 在app delegate中实现application(_:performFetchWithCompletionHandler:)方法,来处理background fetch

就像上面的名称所暗示的那样,background fetch通常从外部获取信息,像一个网络请求。
相比较于finite-length tasks,你大概只有几秒钟来做background fetch ——共识是大概最多30秒。如果你需要下载大的资源,最好使用URLSessionbackground transfer service

AppDelegate中进行如下的设置:

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    
    UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)
    
    return true
  }
  
  func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if let fetchViewController = window?.rootViewController as? FetchViewController
    {
        fetchViewController.fetch {
          fetchViewController.updateUI()
          completionHandler(.newData)
      }
    }
  }

调试:

调试

其它文档:

猜你喜欢

转载自blog.csdn.net/u014084081/article/details/84031692