为什么从 SwiftUI 视图初始值设定项调用时我的发布者订阅会立即取消?

发布于 2025-01-20 13:04:37 字数 1624 浏览 1 评论 0原文

我创建了一个 gravityPublisher (用于接收当前重力矢量的更新)并通过调用以下函数来订阅它:

private func enableGravityDetection(_ gravityEnabled: Bool) {
    if gravityEnabled {
        if cancellable == nil {
            cancellable = gravityProvider
                .gravityPublisher
                .receive(on: RunLoop.main)
                .print()
                .assign(to: \.gravity, on: self)
        }
    } else {
        cancellable?.cancel()
    }
}

gravityPublisher 本身只是一个 CurrentValueSubject< /code>

private var gravitySubject = 
    CurrentValueSubject<CMAcceleration, Never>(CMAcceleration())

已删除为 AnyPublishercancellable 存储为状态属性,如下所示:

@State private var cancellable: Cancellable?

我需要从 SwiftUI 视图中调用此函数。当我从 onAppear 块调用它时,一切都会按预期工作,并且我不断收到重力矢量更新:

struct CustomView: View {
    var body: some View {
        MyView()
            .onAppear {
                enableGravityDetection(true)
            }
    }
}

但是,当我从视图的初始值设定项调用相同(未修改的)函数时,我没有收到任何重力当订阅立即取消时更新:

struct CustomView: View {
    init() {
        enableGravityDetection(true)
    }

    var body: some View {
        MyView()
    }
}

上面流中的 print() 语句在这种情况下打印以下输出:

receive subscription: (ReceiveOn)
request unlimited
receive cancel // ← Why?

为什么会这样以及如何解决这个问题?

我需要在初始化程序中调用此函数,因为有时我需要停止接收重力更新,并且需要在每次重新创建视图时做出决定。 (onAppear 仅调用一次。)

I have created a gravityPublisher (to receive updates in the current gravity vector) and subscribe to it by calling the following function:

private func enableGravityDetection(_ gravityEnabled: Bool) {
    if gravityEnabled {
        if cancellable == nil {
            cancellable = gravityProvider
                .gravityPublisher
                .receive(on: RunLoop.main)
                .print()
                .assign(to: \.gravity, on: self)
        }
    } else {
        cancellable?.cancel()
    }
}

The gravityPublisher itself is just a CurrentValueSubject

private var gravitySubject = 
    CurrentValueSubject<CMAcceleration, Never>(CMAcceleration())

erased to AnyPublisher<CMAcceleration, Never>. The cancellable is stored as a state property as follows:

@State private var cancellable: Cancellable?

I need to call this function from within a SwiftUI view. When I call it from an onAppear block everything works as expected and I continuously receive gravity vector updates:

struct CustomView: View {
    var body: some View {
        MyView()
            .onAppear {
                enableGravityDetection(true)
            }
    }
}

However, when I call the same (unmodified) function from the view's initializer, I don't receive any gravity updates as the subscription is immediately canceled:

struct CustomView: View {
    init() {
        enableGravityDetection(true)
    }

    var body: some View {
        MyView()
    }
}

The print() statement in the stream above prints the following output in this case:

receive subscription: (ReceiveOn)
request unlimited
receive cancel // ← Why?

Why is that and how can I fix this?

I need to call this function in the initializer as I sometimes need to stop receiving gravity updates and need to decide this every time the view is recreated. (onAppear is only called once.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文