【问题标题】:Swift Combine's CombineLatest does not fire in response to an update to one of its publishersSwift Combine 的 CombineLatest 不会响应其发布者之一的更新而触发
【发布时间】:2020-03-25 07:09:01
【问题描述】:

我正在结合两个发布者来确定地图视图的中心坐标应该是什么。这两个发布者是:

  1. 用户的初始位置由CLLocationManager 确定(CLLocationManager 开始发送位置更新后报告的第一个位置)。
  2. 点击“当前位置的中心地图”按钮时用户的当前位置。

在代码中:

    class LocationManager: NSObject, ObservableObject {

        // The first location reported by the CLLocationManager.
        @Published var initialUserCoordinate: CLLocationCoordinate2D?
        // The latest location reported by the CLLocationManager.
        @Published var currentUserCoordinate: CLLocationCoordinate2D?
        // What the current map view center should be.
        @Published var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977) // Default coordinate.

        // A subject whose `send(_:)` method is being called elsewhere every time the user presses a button to center the map on the user's location.
        var centerButtonTappedPublisher: PassthroughSubject<Bool, Never> = PassthroughSubject<Bool, Never>()

        // The combined publisher that is where all my troubles lie.
        var coordinatePublisher: AnyPublisher<CLLocationCoordinate2D, Never> {
            Publishers.CombineLatest($initialUserCoordinate, centerButtonTappedPublisher)
                .map { initialCoord, centerButtonTapped in
                    var latestCoord = initialCoord
                    if centerButtonTapped {
                        latestCoord = self.currentUserCoordinate
                    }
                    return latestCoord
                }
                .replaceNil(with: CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977))
                .eraseToAnyPublisher()
        }

        private var cancellableSet: Set<AnyCancellable> = []

        //... Other irrelevant properties

        private override init() {
            super.init()

            coordinatePublisher
                .receive(on: RunLoop.main)
                .assign(to: \.coordinate, on: self)
                .store(in: &cancellableSet)

            //... CLLocationManager set-up
        }
    }

    extension LocationManager: CLLocationManagerDelegate {

        //...

        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            // We are only interested in the user's most recent location.
            guard let location = locations.last else { return }
            let latestCoord = location.coordinate
            if initialUserCoordinate == nil {
                initialUserCoordinate = latestCoord
            }
            currentUserCoordinate = latestCoord
        }

        //...

    }

$initialUserCoordinatecenterButtonTappedPublisher 这两个发布者都发布了更新 - 我已经确认了这一点。但是,组合发布者coordinatePublisher 仅在点击“当前位置的中心地图”按钮时触发。首次设置 initialUserCoordinate 属性时它永远不会触发。

This question 建议在Publishers.CombineLatest($initialUserCoordinate, centerButtonTappedPublisher) 之后添加.receive(on: RunLoop.main),但这对我不起作用。

我做错了什么?

【问题讨论】:

    标签: swift combine combinelatest


    【解决方案1】:

    您需要使用Publishers.Merge 而不是CombineLatest,请参阅文档:

    对于Publishers.CombineLatest

    从两个发布者那里接收和组合最新元素的发布者。

    对于Publishers.Merge

    任一上游发布者发出事件时发出事件的发布者。

    【讨论】:

    • 谢谢@Sajjon!这就是诀窍。我曾认为 CombineLatest 会在其任何一个发布者发布时发布,但显然都需要先发布一个新值。再次感谢!
    猜你喜欢
    • 2019-11-16
    • 2021-08-21
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多