从函数内部的 ObservedObjects 访问已发布的变量

Posted

技术标签:

【中文标题】从函数内部的 ObservedObjects 访问已发布的变量【英文标题】:Accessing published vars from ObservedObjects inside a function 【发布时间】:2020-03-15 12:55:07 【问题描述】:

我有 2 个类(一个用于 HealthKit,另一个用于 CoreMotion),它们为一些已发布的变量分配值,然后我通过我的主 swiftui 文件访问这些变量。我的内容视图正确更新。到现在为止还挺好。现在我想将这些变量的输出记录到控制台。我可以通过直接从类中记录来直接执行此操作,但我遇到的问题是我需要将两个类的输出放在一行中。我为此编写了一个新函数,但值没有得到更新。谁能帮助我?是不是因为函数只被调用一次,所以所有参数总是函数被调用时的参数?

我的主要 contentView.swift 文件:

import SwiftUI

struct ContentView: View 

    @State var isActive: Bool = false
    @ObservedObject var motion = MotionManager()
    @ObservedObject var health = HealthKitManager()

    private var logger = ConsoleLogger()

    var body: some View 
        ScrollView 
            VStack(alignment: .leading) 
                Indicator(title: "X:", value: motion.rotationX)
                Indicator(title: "Y:", value: motion.rotationY)
                Indicator(title: "Z:", value: motion.rotationZ)
                Divider()
                Indicator(title: "Pitch:", value: motion.pitch)
                Indicator(title: "Roll:", value: motion.roll)
                Indicator(title: "Yaw:", value: motion.yaw)
                Divider()
                Indicator(title: "HR:", value: health.heartRateValue)
                
            .padding(.horizontal, 10)
            Button(action: 
                self.isActive.toggle()
                self.isActive ? self.start() : self.stop()
            ) 
                Text(isActive ? "Stop" : "Start")
            
            .background(isActive ? Color.green : Color.blue)
            .cornerRadius(10)
        .onAppear 
            self.health.autorizeHealthKit()
        
    

    private func start() 
        self.motion.startMotionUpdates()
        self.health.fetchHeartRateData(quantityTypeIdentifier: .heartRate)
        self.logger.startLogging(rotationX: self.motion.rotationX, rotationY: self.motion.rotationY, rotationZ: self.motion.rotationZ, pitch: self.motion.pitch, roll: self.motion.roll, yaw: self.motion.yaw, heartRate: self.health.heartRateValue)
    

    private func stop() 
        self.motion.stopMotionUpdates()
        self.health.stopFetchingHeartRateData()
        self.logger.stopLogging()
    



struct Indicator: View 
    var title: String
    var value: Double

    var body: some View 
        HStack 
            Text(title)
                .font(.footnote)
                .foregroundColor(.blue)
            Text("\(value)")
                .font(.footnote)
        
    

这是我的 consoleLogger.swift 文件

import Foundation
import os.log

class ConsoleLogger 

    private var timer: Timer?

    func startLogging(rotationX: Double, rotationY: Double, rotationZ: Double, pitch: Double, roll: Double, yaw: Double, heartRate: Double) 

        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block:  _ in
            let timestamp = Date().timeIntervalSince1970
            os_log("Motion: %@, %@, %@, %@, %@, %@, %@, %@",
                   String(timestamp),
                   String(rotationX),
                   String(rotationY),
                   String(rotationZ),
                   String(pitch),
                   String(roll),
                   String(yaw),
                   String(heartRate)
            )
        )
    

    func stopLogging() 
        timer?.invalidate()
    

所以我的计时器正在工作,我每秒钟都会在控制台中看到输出,但是所有变量(在类中创建的时间戳除外)的初始值都是 0.0。知道怎么解决吗?

【问题讨论】:

已调整。 :) 谢谢 顺便说一句,与问题无关,但关于您的 startLogging 的所有内容都是难闻的气味。这一堆值应该用description 捆绑到一个结构中,这样你的os_log 所要做的就是打印那个结构。 【参考方案1】:

问题不只是您只使用初始值集调用startLogging 一次吗?然后,您只需一遍又一遍地打印 same 组值。您无法查看实际的数据(当前持有您的motionhealth 对象)来查看现在是什么。

【讨论】:

我个人会做的是使用Combine框架来订阅你观察到的对象,并使用.combineLatest.throttle最多每秒输出一次当前数据。 是的,可能。我会尝试为它找到解决方案。顺便说一句......你能解释一下“这堆值应该捆绑到一个带有描述的结构中,这样你的 os_log 所要做的就是打印那个结构”是什么意思吗? 对不起,我不知道怎么说更直接了。 感谢您指出 .combineLatest 和 .throttle。现在阅读Combine,一切都开始变得清晰 我写了一个教程:apeth.com/UnderstandingCombine/operators/operatorsJoiners/…

以上是关于从函数内部的 ObservedObjects 访问已发布的变量的主要内容,如果未能解决你的问题,请参考以下文章

核心数据 NSManagedObject - ObservedObjects 未更新

iOS Swiftui App 返回前台重置 ObservedObjects

无法从 if 正文访问函数内部声明的变量

如何从类函数内部访问对象属性[重复]

Python:从内部类访问外部私有函数

如何从jsp标签内部访问函数中的变量