Swift Joint - 为 CoreLocation 创建发布者

标签 swift reactive-programming core-location combine publisher

我才刚刚开始学习组合,所以对我来说还是有点模糊。我想创建一个自定义的 Publisher,它将使用 CLLocationManager 来公开当前用户位置。我希望它以这样的方式工作,即 locationManager 仅在有一些订阅者连接时才开始更新位置。在所有订阅者被删除、取消等之后,它应该停止更新位置。这可以吗?我怎样才能创建这样一个发布者?这也是正确的方法吗?还是有问题?

最佳答案

您想要的基础知识非常简单。有一个来自Using Combine的例子用一个充当代理的对象包装 CoreLocation,返回 CLHeading 的发布者更新。

CoreLocation 本身不会自动启动或停止此类事情,并且在代理对象中我复制了该模式以允许您手动启动和停止更新过程。

核心代码在 https://github.com/heckj/swiftui-notes/blob/master/UIKit-Combine/LocationHeadingProxy.swift

import Foundation
import Combine
import CoreLocation

final class LocationHeadingProxy: NSObject, CLLocationManagerDelegate {
    let mgr: CLLocationManager
    private let headingPublisher: PassthroughSubject<CLHeading, Error>
    var publisher: AnyPublisher<CLHeading, Error>

    override init() {
        mgr = CLLocationManager()
        headingPublisher = PassthroughSubject<CLHeading, Error>()
        publisher = headingPublisher.eraseToAnyPublisher()

        super.init()
        mgr.delegate = self
    }

    func enable() {
        mgr.startUpdatingHeading()
    }

    func disable() {
        mgr.stopUpdatingHeading()
    }
    // MARK - delegate methods
    func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
        headingPublisher.send(newHeading)
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        headingPublisher.send(completion: Subscribers.Completion.failure(error))
    }
}

这并不能完全满足您要求的所有要求,因为它不会在订阅时自动启动更新,但我怀疑您可以扩展它以启用该功能。

到目前为止,我还没有深入研究通过实现协议(protocol)所需的所有方法来创建自己的发布者,因此我没有扩展该机制的详细信息。 Combine本身有ConnectablePublisher的概念尽管大多数发布者和运算符(operator)都会在创建发布者或订阅时触发,但当您想要对更新进行显式控制时。

一般来说,如果您应该这样做,您的用例可以更好地回答您的问题。在某些情况下,您在更新 View 之前创建管道并订阅 - 如果是这种情况,那么推迟请求后台更新将为您节省一些处理能力和能源消耗。

在使用此 CoreLocation 发布者的 UIKit 示例中,我还拥有适当的机制来验证是否已请求权限以允许位置更新,嵌入示例 View Controller 中:https://github.com/heckj/swiftui-notes/blob/master/UIKit-Combine/HeadingViewController.swift

关于Swift Joint - 为 CoreLocation 创建发布者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59007014/

相关文章:

xcode - 如何在 Swift 中创建全局变量?

android - Kotlin 泛型方法和继承

swift - UICollectionView 数据源和委托(delegate)导致应用程序终止

ios - Swift - 缓慢的 UITableView 滚动(从设备存储加载图像)

swift - Swift 中数组的通用扩展

java - RxJava 组合请求序列

java - 如何在不丢失数据的情况下与不同的发布者建立 react 性管道?

iphone - 显示禁用位置服务的用户位置

ios - 从 AppDelegate 和 ViewController 访问 locaitonManager

ios - iPhone SDK:CLocationAccuracy。什么常量映射到什么定位技术?