从另一个类访问变量给出0 swift



所以我想从另一个叫做PoseEstimator的类访问这个变量squatCount,并在另一个viewController的UILabel中打印出来。但是由于某些原因,当我这样做时,标签将squatCount的值打印为零,即使变量明显增加。

我在网上读了几个小时的论坛,我通过谈论实现一些全局变量或单例或一些enum的东西,我真的不理解它对swift来说很新。所以我想找出发生这种情况的原因并解决它。非常感谢你的帮助。

PoseEstimator代码:

import AVFoundation
import Vision
import Combine
import SwiftUI
//declaring PoseEstimator as a class. We need to add AVCaptureVideoDataOutputSampleBufferDelegate and make it an obserable object to use PoseEsimation on our AVFoundation video output
class PoseEstimator: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, ObservableObject {
let sequenceHandler = VNSequenceRequestHandler()
@Published var bodyParts = [VNHumanBodyPoseObservation.JointName : VNRecognizedPoint]() //declare body parts as a published variable storing the coordinates of the body joints from Vision

var seconds = 0 //This variable will hold a starting value of seconds. It could be any amount above 0.

var timer = Timer()

var isTimerRunning = false//This will be used to make sure only one timer is created at a time.


var elaspedTime = Float()//we need it to declare it as a float because we would be storing numbers with decimals inside//This one is for Planks the one above is to fix a lunge bug
var halfburpee = 0
var halfLunge = 0
var halfPU = 0
var uprightLunge = false
var wasInBottomPosition = false       //declare the position of the player as top or bottom
var wasInBottomLunge = false
var wasInTopJJ = false
var wasInBottomPU = false
var wasInDeadLift = false
var wasInMidBurpee = false
var wasInBottomBurpee = false
var wasinupright = false
var wasinalmostdoneBurpee = false
var down = false
var cooldown = true


@Published var squatCount = 0          //declare variables for no of exercises done
@Published var LungeCounter = 0
@Published var JumpingJackCounter = 0
@Published var PushupCounter = 0
@Published var BurpeesCounter = 0
@Published var SLDeadliftsCounter = 0
@Published var caloriesBurntSquats = Float(0)
@Published var caloriesBurntLunges = Float(0)
@Published var caloriesBurntJJ = Float()
@Published var caloriesBurntPushups = Float(0)
@Published var caloriesBurntBurpees = Float(0)
@Published var caloriesBurntSLD = Float(0)
@Published var isGoodSquatPosture = true
@Published var isGoodLungePosture = true
@Published var isGoodJJPosture = true
@Published var isGoodPUPosture = true
@Published var isGoodSLDPosture = true

var subscriptions = Set<AnyCancellable>()        //for combine to store the proessed coordinates of Vision

func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self,   selector: (#selector(PoseEstimator.updateTimer)), userInfo: nil, repeats: true)
}

@objc func updateTimer() {
seconds += 1     //This will decrement(count down)the seconds.
if seconds >= 2{
self.cooldown = false
}else{
self.cooldown = true
}
}

override init() {
super.init()
$bodyParts
.dropFirst()
.sink(receiveValue: { bodyParts in self.Process(bodyParts: bodyParts)})
.store(in: &subscriptions)
}

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
let humanBodyRequest = VNDetectHumanBodyPoseRequest(completionHandler: detectedBodyPose)
do {
try sequenceHandler.perform(            //sent request to detect human body joints from AVFoundation
[humanBodyRequest],
on: sampleBuffer,
orientation: .right)
} catch {
print(error.localizedDescription)
}
}
func detectedBodyPose(request: VNRequest, error: Error?) {
guard let bodyPoseResults = request.results as? [VNHumanBodyPoseObservation]       //set bodyPoseResults as the the reuslts from Vision
else { return }
guard let bodyParts = try? bodyPoseResults.first?.recognizedPoints(.all) else { return }
DispatchQueue.main.async {
self.bodyParts = bodyParts            //set bodyparts as the recognised points from vision
}
}

func Process(bodyParts: [VNHumanBodyPoseObservation.JointName : VNRecognizedPoint]) { // function for processing results from vision


let rightKnee = bodyParts[.rightKnee]!.location  // declare variables that we need to determine if the player is doing exercise
let leftKnee = bodyParts[.leftKnee]!.location
let rightHip = bodyParts[.rightHip]!.location
let rightAnkle = bodyParts[.rightAnkle]!.location
let leftAnkle = bodyParts[.leftAnkle]!.location
let leftHip = bodyParts[.leftHip]!.location
let rightShoulder = bodyParts[.rightShoulder]!.location
let leftShoulder = bodyParts[.leftShoulder]!.location
let rightElbow = bodyParts[.rightElbow]!.location
let rightWrist = bodyParts[.rightWrist]!.location
let leftWrist = bodyParts[.leftWrist]!.location
let root = bodyParts[.root]!.location
let neck = bodyParts[.neck]!.location

//squats angles decleration
let firstAngle = atan2(rightHip.y - rightKnee.y, rightHip.x - rightKnee.x) // simple trigonometry to determine the angles required
let secondAngle = atan2(rightAnkle.y - rightKnee.y, rightAnkle.x - rightKnee.x)
var angleDiffRadians = firstAngle - secondAngle //calculate the difference between the angles

//Jumping Jacks angles decleration
let firstJJAngle = atan2(rightHip.y - rightShoulder.y, rightHip.x - rightShoulder.x)
let secondJJAngle = atan2(rightElbow.y - rightShoulder.y, rightElbow.x - rightShoulder.x) //calculate angles of armpit
var JJangleDiffRadians = firstJJAngle - secondJJAngle

let firstrootAngle = atan2(rightKnee.y - root.y, rightKnee.x - root.x)
let secondrootAngle = atan2(leftKnee.y - root.y, leftKnee.x - root.x)
var rootangleDiffRadians = firstrootAngle + secondrootAngle

//Pushups anlges decleration
let firstPUAngle = atan2(rightShoulder.y - rightElbow.y, rightShoulder.x - rightElbow.x)
let secondPUAngle = atan2(rightWrist.y - rightElbow.y, rightWrist.x - rightElbow.x)
var PUAngleDiffRadians = firstPUAngle - secondPUAngle

//SLDeadlifts angles decleration
let firstDeadliftAngle = atan2(neck.y - root.y, neck.x - root.x)
let secondDeadLiftAngle = atan2(rightKnee.y - root.y, rightKnee.x - root.x)
var SLDangleDiffRadians = firstDeadliftAngle - secondDeadLiftAngle

let firstLegAngle = atan2(leftAnkle.y - leftKnee.y, leftAnkle.x - leftKnee.x)
let secondLegAngle = atan2(leftHip.y - leftKnee.y, leftHip.x - leftKnee.x)
var legAngleDiffRadians = firstLegAngle - secondLegAngle

//Burpees angles decleration
let firstBurpeeAngle = atan2(rightElbow.y - rightShoulder.y, rightElbow.x - rightShoulder.x)
let secondBurpeeAngle = atan2(neck.y - rightShoulder.y, neck.x - rightShoulder.x)
var BurpeeAngleDiffRadians = firstBurpeeAngle - secondBurpeeAngle

//conversion of angles in radians to degrees
while angleDiffRadians < 0 {
angleDiffRadians += CGFloat(2 * Double.pi)
}
while JJangleDiffRadians < 0{
JJangleDiffRadians += CGFloat(2 * Double.pi)
}
while rootangleDiffRadians < 0{
rootangleDiffRadians += CGFloat(2 * Double.pi)
}
while PUAngleDiffRadians < 0{
PUAngleDiffRadians += CGFloat(2 * Double.pi)
}
while SLDangleDiffRadians < 0{
SLDangleDiffRadians += CGFloat(2 * Double.pi)
}
while legAngleDiffRadians < 0{
legAngleDiffRadians += CGFloat(2 * Double.pi)
}
while BurpeeAngleDiffRadians < 0{
BurpeeAngleDiffRadians += CGFloat(2 * Double.pi)
}


let angleDiffDegrees = Int(angleDiffRadians * 180 / .pi)
let rootangleDIffDegrees = Int(rootangleDiffRadians * 180 / .pi)
let JJangleDIffDegrees = Int(JJangleDiffRadians * 180 / .pi)

let PUAngleDiffDegrees = Int(PUAngleDiffRadians * 180 / .pi)
let SLDAngleDiffDegrees = Int(SLDangleDiffRadians * 180 / .pi)
let legAngleDiffDegrees = Int(legAngleDiffRadians * 180 / .pi)
let BurpeeAngleDiffDegrees = Int(BurpeeAngleDiffRadians * 180 / .pi)


//process whether the player is doing a squat
if angleDiffDegrees > 150 && self.wasInBottomPosition == true{ // determine if the player is doing a squat
self.wasInBottomPosition = false
self.squatCount += 1
self.caloriesBurntSquats = Float(self.squatCount) * 0.32
}

//process whether the player is doing a lunge
if angleDiffDegrees > 160 && wasInBottomLunge == true{
self.LungeCounter += 1
self.wasInBottomLunge = false
self.caloriesBurntLunges = Float(self.LungeCounter) * 0.3
}

//process whether the player is doing a Jumping Jack
if rootangleDIffDegrees < 180 && JJangleDIffDegrees <= 90 && self.wasInTopJJ{
self.JumpingJackCounter += 1
self.wasInTopJJ = false
self.caloriesBurntJJ = Float(self.JumpingJackCounter) * 0.2
}
//process whether the player is doing a pushup
if PUAngleDiffDegrees > 167 && wasInBottomPU{
halfPU += 1
wasInBottomPU = false
self.caloriesBurntPushups = Float(self.PushupCounter) * 0.6
}

if halfPU >= 2{
self.halfPU = 0
self.PushupCounter += 1
}
//process whether the player is doing a SLDeadlift
if SLDAngleDiffDegrees >= 215 && wasInDeadLift{
SLDeadliftsCounter += 1
wasInDeadLift = false
self.caloriesBurntSLD = Float(self.SLDeadliftsCounter) * 0.2
}
//process whether the player is doing a burpee
if self.wasinupright == true && self.wasinalmostdoneBurpee == true{
self.halfburpee += 1
self.wasinupright = false
self.wasInBottomBurpee = false
self.wasInMidBurpee = false
self.down = false
self.wasinalmostdoneBurpee = false
self.caloriesBurntBurpees = Float(self.BurpeesCounter) * 0.5
}
if self.halfburpee >= 2{
self.BurpeesCounter += 1
self.halfburpee = 0
}

//proess whether the player is in the top/bottom position of the exercise
let hipHeight = rightHip.y
let lefthipHeight = leftHip.y
let kneeHeight = rightKnee.y
let leftkneeHeight = leftKnee.y
let ankleheight = rightAnkle.y
let shoulderheight = rightShoulder.y
let elbowHeight = rightElbow.y
let wristheight = leftWrist.y


//squats
if hipHeight < kneeHeight { //determing if the user is in the bottom position of the squat
self.wasInBottomPosition = true
}
//lunges
if leftkneeHeight <= ankleheight {
self.wasInBottomLunge = true
}
if leftkneeHeight == kneeHeight {
self.uprightLunge = true
}else{
self.uprightLunge = false
}

//Jumping jacks
if elbowHeight > shoulderheight && JJangleDIffDegrees >= 130 && rootangleDIffDegrees > 175{ // determining if the user's arms are above the shoulders
self.wasInTopJJ = true
}
//Pushups
if PUAngleDiffDegrees <= 150 {
self.wasInBottomPU = true
}
//SL deadlifts
if hipHeight > lefthipHeight{
self.wasInDeadLift = true
}
//Burpees
if BurpeeAngleDiffDegrees >= 240{
self.down = true
}
if kneeHeight >= elbowHeight{
self.wasInMidBurpee = true
}
if kneeHeight < elbowHeight && self.wasInMidBurpee == true && self.down == true{
self.wasInBottomBurpee = true
}
if kneeHeight >= elbowHeight && self.wasInBottomBurpee == true{
self.wasinalmostdoneBurpee = true
}
if wristheight > ankleheight{
self.wasinupright = true
}else{
self.wasinupright = false
}

let kneeDistance = rightKnee.distance(to: leftKnee)
let ankleDistance = rightAnkle.distance(to: leftAnkle)
let wristDistance = rightWrist.distance(to: leftWrist)
let shoulderDistance = rightShoulder.distance(to: leftShoulder)


if ankleDistance > kneeDistance { //checking if the posture of the player doing squats is good
self.isGoodSquatPosture = false
} else {
self.isGoodSquatPosture = true
}

if rootangleDIffDegrees >= 180 && elbowHeight <= shoulderheight{ //posture check for Jumping Jacks
self.isGoodJJPosture = false
} else{
self.isGoodJJPosture = true
}
if (wristDistance - 1) != shoulderDistance { //posture check for PushUps
self.isGoodPUPosture = false
}else{
self.isGoodPUPosture = true
}
if legAngleDiffDegrees > 175{ //posture check for Single-Leg Deadlifts
self.isGoodSLDPosture = false
}else{
self.isGoodSLDPosture = true
}

}
}

my viewController code:

import SwiftUI
class DoneViewController: UIViewController {

var exerciseLoaded = false
var burntCalories = Float()

let poseEstimator = PoseEstimator()

@IBOutlet weak var repsDone: UILabel!

@IBOutlet weak var caloriesBurnt: UILabel!

@IBOutlet weak var exerciseMoreBtn: UIButton!

@IBOutlet weak var HomeWhenDone:
UIButton!


override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
exerciseMoreBtn.layer.cornerRadius = 10
HomeWhenDone.layer.cornerRadius = 10
repsDone.text = String(poseEstimator.squatCount)
}

将此单例添加到PoseEstimator类

static let shared = PoseEstimator()

then in DoneViewController change

let poseEstimator = PoseEstimator()

:

let poseEstimator = PoseEstimator.shared

这样做的原因是它将是对同一个对象的引用。当前你正在通过从视图控制器调用init创建一个新实例。你也可以在导航过程中传递一个引用到视图控制器,或者检索它,但这是让你继续的最简单的方法。

最新更新