gpt4 book ai didi

ios - 无法在 swift 3 的结构中获取返回值

转载 作者:行者123 更新时间:2023-11-28 15:10:56 26 4
gpt4 key购买 nike

我有这段代码:

//
// Measurement.swift
// BicycleSpeed

import Foundation
import CoreBluetooth

// CSC Measurement
// https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.csc_measurement.xml
//
// Flags : 1 byte. Bit 0: Wheel. Bit 1: Crank
// Cumulative Wheel revolutions: 4 bytes uint32
// Last wheel event time: 2 bytes. uint16 (1/1024s)
// Cumulative Crank revolutions: 2 bytes uint16
// Last cranck event time: 2 bytes. uint16 (1/1024s)


struct Measurement : CustomDebugStringConvertible {

let hasWheel:Bool
let hasCrank:Bool
let cumulativeWheel:UInt32
let lastWheelEventTime:TimeInterval
let cumulativeCrank:UInt16
let lastCrankEventTime:TimeInterval
let wheelSize:UInt32


init(data:Data, wheelSize:UInt32) {

self.wheelSize = wheelSize
// Flags
var flags:UInt8=0
(data as NSData).getBytes(&flags, range: NSRange(location: 0, length: 1))

hasWheel = ((flags & BTConstants.WheelFlagMask) > 0)
hasCrank = ((flags & BTConstants.CrankFlagMask) > 0)

var wheel:UInt32=0
var wheelTime:UInt16=0
var crank:UInt16=0
var crankTime:UInt16=0

var currentOffset = 1
var length = 0

if ( hasWheel ) {

length = MemoryLayout<UInt32>.size
(data as NSData).getBytes(&wheel, range: NSRange(location: currentOffset, length: length))
currentOffset += length

length = MemoryLayout<UInt16>.size
(data as NSData).getBytes(&wheelTime, range: NSRange(location: currentOffset, length: length))
currentOffset += length
}

if ( hasCrank ) {

length = MemoryLayout<UInt16>.size
(data as NSData).getBytes(&crank, range: NSRange(location: currentOffset, length: length))
currentOffset += length

length = MemoryLayout<UInt16>.size
(data as NSData).getBytes(&crankTime, range: NSRange(location: currentOffset, length: length))
currentOffset += length
}

cumulativeWheel = CFSwapInt32LittleToHost(wheel)
lastWheelEventTime = TimeInterval( Double(CFSwapInt16LittleToHost(wheelTime))/BTConstants.TimeScale)
cumulativeCrank = CFSwapInt16LittleToHost(crank)
lastCrankEventTime = TimeInterval( Double(CFSwapInt16LittleToHost(crankTime))/BTConstants.TimeScale)

}

func timeIntervalForCurrentSample( _ current:TimeInterval, previous:TimeInterval ) -> TimeInterval {
var timeDiff:TimeInterval = 0
if( current >= previous ) {
timeDiff = current - previous
}
else {
// passed the maximum value
timeDiff = ( TimeInterval((Double( UINT16_MAX) / BTConstants.TimeScale)) - previous) + current
}
return timeDiff

}

func valueDiffForCurrentSample<T:UnsignedInteger>( _ current:T, previous:T , max:T) -> T {

var diff:T = 0
if ( current >= previous ) {
diff = current - previous
}
else {
diff = ( max - previous ) + current
}
return diff
}


func valuesForPreviousMeasurement( _ previousSample:Measurement? ) -> ( cadenceinRPM:Double?, distanceinMeters:Double?, speedInMetersPerSecond:Double?)? {


var distance:Double?, cadence:Double?, speed:Double?
guard let previousSample = previousSample else {
return nil
}
if ( hasWheel && previousSample.hasWheel ) {
let wheelTimeDiff = timeIntervalForCurrentSample(lastWheelEventTime, previous: previousSample.lastWheelEventTime)
let valueDiff = valueDiffForCurrentSample(cumulativeWheel, previous: previousSample.cumulativeWheel, max: UInt32.max)

distance = Double( valueDiff * wheelSize) / 1000.0 // distance in meters
if distance != nil && wheelTimeDiff > 0 {
speed = (wheelTimeDiff == 0 ) ? 0 : distance! / wheelTimeDiff // m/s
}
}

if( hasCrank && previousSample.hasCrank ) {
let crankDiffTime = timeIntervalForCurrentSample(lastCrankEventTime, previous: previousSample.lastCrankEventTime)
let valueDiff = Double(valueDiffForCurrentSample(cumulativeCrank, previous: previousSample.cumulativeCrank, max: UInt16.max))

cadence = (crankDiffTime == 0) ? 0 : Double(60.0 * valueDiff / crankDiffTime) // RPM

}
print( "Cadence: \(String(describing: cadence)) RPM. Distance: \(String(describing: distance)) meters. Speed: \(String(describing: speed)) Km/h" )
return ( cadenceinRPM:cadence, distanceinMeters:distance, speedInMetersPerSecond:speed)



}

var debugDescription:String {
get {
return "Wheel Revs: \(cumulativeWheel). Last wheel event time: \(lastWheelEventTime). Crank Revs: \(cumulativeCrank). Last Crank event time: \(lastCrankEventTime)"
}
}

var myMeasurement = ((Measurement?) -> (cadenceinRPM: Double?, DistanceinMeters: Double?, speedinMetersPerSecond: Double?)).self


struct dataVariables {

static var mySpeed = myMeasurement.speedInMetersPerSecond


static var myCadence : Double?
static var miDistance : Double?

static var myLastWheelEventTime : Double? = Measurement.valuesForPreviousMeasurement(lastWheelEventTime)

static var myLastCrankEventTime : Double? = Measurement.valuesForPreviousMeasurement(lastCrankEventTime)


}
}


}

我正在尝试将返回值 cadenceinRPM、distanceinMeters、speedingMetersPerSecond 分配给 struct dataVariables 内的静态变量
以及 lastWheelEventTime 和 lastCrankEventTime,因此我可以在另一个类中访问它们,但我遇到以下错误:关于 var mySpeed:实例成员“myMeasurement”不能用于类型“Measurement”在 var myLastWheelEventTime 和 var myLastCrankEventTime 上:实例成员“valuesForPreviousMeasurement”不能用于类型“Measurement”;您的意思是改用这种类型的值吗?怎么能引用那些返回值呢?有人可以解释错误吗?我搜索了其他类似的问题,但我还没有找到解决方案我试图将 var myVariable 更改为

var myMeasurement = Measurement.self

但错误保持不变。

和其他代码

    //
// CadenceSensor.swift

import Foundation
import CoreBluetooth

/*
// Bluetooth "Cycling Speed and Cadence"
https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.cycling_speed_and_cadence.xml

Service Cycling Speed and Cadence. Characteristic [2A5B] // Measurement
Service Cycling Speed and Cadence. Characteristic [2A5C] // Supported Features
Service Cycling Speed and Cadence. Characteristic [2A5D] // Sensor location
Service Cycling Speed and Cadence. Characteristic [2A55] // Control Point

*/

public struct BTConstants {
static let CadenceService = "1816"
static let CSCMeasurementUUID = "2a5b"
static let CSCFeatureUUID = "2a5c"
static let SensorLocationUUID = "2a5d"
static let ControlPointUUID = "2a55"
static let WheelFlagMask:UInt8 = 0b01
static let CrankFlagMask:UInt8 = 0b10
static let DefaultWheelSize:UInt32 = UInt32(myVariables.circonferenzaRuota!) // In millimiters. 700x30 (by default my bike's wheels) :)
static let TimeScale = 1024.0
}

protocol CadenceSensorDelegate {

func errorDiscoveringSensorInformation(_ error:NSError)
func sensorReady()
func sensorUpdatedValues( speedInMetersPerSecond speed:Double?, cadenceInRpm cadence:Double?, distanceInMeters distance:Double? )
}

class CadenceSensor: NSObject {

let peripheral:CBPeripheral
var sensorDelegate:CadenceSensorDelegate?
var measurementCharasteristic:CBCharacteristic?
var lastMeasurement:Measurement?
let wheelCircunference:UInt32


init(peripheral:CBPeripheral , wheel:UInt32=BTConstants.DefaultWheelSize) {
self.peripheral = peripheral
wheelCircunference = wheel
}

func start() {
self.peripheral.discoverServices(nil)
self.peripheral.delegate = self
}


func stop() {
if let measurementCharasteristic = measurementCharasteristic {
peripheral.setNotifyValue(false, for: measurementCharasteristic)
}

}

func handleValueData( _ data:Data ) {

let measurement = Measurement(data: data, wheelSize: wheelCircunference)
print("\(measurement)")

let values = measurement.valuesForPreviousMeasurement(lastMeasurement)
lastMeasurement = measurement

sensorDelegate?.sensorUpdatedValues(speedInMetersPerSecond: values?.speedInMetersPerSecond, cadenceInRpm: values?.cadenceinRPM, distanceInMeters: values?.distanceinMeters)
}
}



extension CadenceSensor : CBPeripheralDelegate {


func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
guard error == nil else {
sensorDelegate?.errorDiscoveringSensorInformation(NSError(domain: CBErrorDomain, code: 0, userInfo: [NSLocalizedDescriptionKey:NSLocalizedString("Error receiving measurements updates", comment:"")]))

return
}
print("notification status changed for [\(characteristic.uuid)]...")
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

print("Updated [\(characteristic.uuid)]...")

guard error == nil , let data = characteristic.value else {

return
}

handleValueData(data)

}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard error == nil else {
sensorDelegate?.errorDiscoveringSensorInformation(error! as NSError)
return
}
// Find the cadence service
guard let cadenceService = peripheral.services?.filter({ (service) -> Bool in
return service.uuid == CBUUID(string: BTConstants.CadenceService)
}).first else {

sensorDelegate?.errorDiscoveringSensorInformation(NSError(domain: CBErrorDomain, code: NSNotFound, userInfo: [NSLocalizedDescriptionKey:NSLocalizedString("Cadence service not found for this peripheral", comment:"")]))
return
}
// Discover the cadence service characteristics
peripheral.discoverCharacteristics(nil, for:cadenceService )
print("Cadence service discovered")

}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

guard let characteristics = service.characteristics else {
sensorDelegate?.errorDiscoveringSensorInformation(NSError(domain: CBErrorDomain, code: NSNotFound, userInfo: [NSLocalizedDescriptionKey:NSLocalizedString("No characteristics found for the cadence service", comment:"")]))
return

}

print("Received characteristics");

// Enable notifications for the measurement characteristic
for characteristic in characteristics {

print("Service \(service.uuid). Characteristic [\(characteristic.uuid)]")

if characteristic.uuid == CBUUID(string: BTConstants.CSCMeasurementUUID) {

print("Found measurement characteristic. Subscribing...")
peripheral.setNotifyValue(true, for: characteristic)
measurementCharasteristic = characteristic

}
}
sensorDelegate?.sensorReady()

}

}

和其他代码

    //
// MainViewController.swift
// BicycleSpeed


import UIKit
import CoreBluetooth

class MainViewController: UIViewController {


struct Constants {

static let ScanSegue = "ScanSegue"
static let SensorUserDefaultsKey = "lastsensorused"
}

var bluetoothManager:BluetoothManager!
var sensor:CadenceSensor?
weak var scanViewController:ScanViewController?
var infoViewController:InfoTableViewController?
var accumulatedDistance:Double?

lazy var distanceFormatter:LengthFormatter = {

let formatter = LengthFormatter()
formatter.numberFormatter.maximumFractionDigits = 1

return formatter
}()

//@IBOutlet var labelBTStatus:UILabel!
@IBOutlet var scanItem:UIBarButtonItem!
@IBOutlet weak var idLabel: UILabel!


override func viewDidLoad() {

bluetoothManager = BluetoothManager()
bluetoothManager.bluetoothDelegate = self
scanItem.isEnabled = false

}

deinit {
disconnectSensor()
}

@IBAction func unwindSegue( _ segue:UIStoryboardSegue ) {
bluetoothManager.stopScan()
guard let sensor = (segue as? ScanUnwindSegue)?.sensor else {
return
}
print("Need to connect to sensor \(sensor.peripheral.identifier)")
connectToSensor(sensor)

}

func disconnectSensor( ) {
if sensor != nil {
bluetoothManager.disconnectSensor(sensor!)
sensor = nil
}
accumulatedDistance = nil
}

func connectToSensor(_ sensor:CadenceSensor) {

self.sensor = sensor
bluetoothManager.connectToSensor(sensor)
// Save the sensor ID
UserDefaults.standard.set(sensor.peripheral.identifier.uuidString, forKey: Constants.SensorUserDefaultsKey)
UserDefaults.standard.synchronize()

}
// TODO: REconnect. Try this every X seconds
func checkPreviousSensor() {

guard let sensorID = UserDefaults.standard.object(forKey: Constants.SensorUserDefaultsKey) as? String else {
return
}
guard let sensor = bluetoothManager.retrieveSensorWithIdentifier(sensorID) else {
return
}
self.sensor = sensor
connectToSensor(sensor)

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let infoVC = segue.destination as? InfoTableViewController {
infoViewController = infoVC
}
if segue.identifier == Constants.ScanSegue {

// Scan segue
bluetoothManager.startScan()
scanViewController = (segue.destination as? UINavigationController)?.viewControllers.first as? ScanViewController
}

}

}

extension MainViewController : CadenceSensorDelegate {

func errorDiscoveringSensorInformation(_ error: NSError) {
print("An error ocurred disconvering the sensor services/characteristics: \(error)")
}

func sensorReady() {
print("Sensor ready to go...")
accumulatedDistance = 0.0
}

func updateSensorInfo() {
let name = sensor?.peripheral.name ?? ""
let uuid = sensor?.peripheral.identifier.uuidString ?? ""

OperationQueue.main.addOperation { () -> Void in
self.infoViewController?.showDeviceName(name , uuid:uuid )
}
}


func sensorUpdatedValues( speedInMetersPerSecond speed:Double?, cadenceInRpm cadence:Double?, distanceInMeters distance:Double? ) {

accumulatedDistance? += distance ?? 0
let distanceText = (accumulatedDistance != nil && accumulatedDistance! >= 1.0) ? distanceFormatter.string(fromMeters: accumulatedDistance!) : "N/A"
let speedText = (speed != nil) ? distanceFormatter.string(fromValue: speed!*3.6, unit: .kilometer) + NSLocalizedString("/h", comment:"(km) Per hour") : "N/A"
let cadenceText = (cadence != nil) ? String(format: "%.2f %@", cadence!, NSLocalizedString("RPM", comment:"Revs per minute") ) : "N/A"

OperationQueue.main.addOperation { () -> Void in

self.infoViewController?.showMeasurementWithSpeed(speedText , cadence: cadenceText, distance: distanceText )
}
}


}

extension MainViewController : BluetoothManagerDelegate {

func stateChanged(_ state: CBCentralManagerState) {
print("State Changed: \(state)")
var enabled = false
var title = ""
switch state {
case .poweredOn:
title = "Bluetooth ON"
enabled = true
// When the bluetooth changes to ON, try to reconnect to the previous sensor
checkPreviousSensor()

case .resetting:
title = "Reseeting"
case .poweredOff:
title = "Bluetooth Off"
case .unauthorized:
title = "Bluetooth not authorized"
case .unknown:
title = "Unknown"
case .unsupported:
title = "Bluetooth not supported"
}
infoViewController?.showBluetoothStatusText( title )
scanItem.isEnabled = enabled
}


func sensorConnection( _ sensor:CadenceSensor, error:NSError?) {
print("")
guard error == nil else {
self.sensor = nil
print("Error connecting to sensor: \(sensor.peripheral.identifier)")
updateSensorInfo()
accumulatedDistance = nil
return
}
self.sensor = sensor
self.sensor?.sensorDelegate = self
print("Sensor connected. \(String(describing: sensor.peripheral.name)). [\(sensor.peripheral.identifier)]")
updateSensorInfo()

sensor.start()
}


func sensorDisconnected( _ sensor:CadenceSensor, error:NSError?) {
print("Sensor disconnected")
self.sensor = nil
}

func sensorDiscovered( _ sensor:CadenceSensor ) {
scanViewController?.addSensor(sensor)
}



}

在 MainViewController.swift 中,有一个 func sensorUpdatedValues 将我想要的三个值转换为字符串并初始化 InfoTableViewController.swift 中的 func showMeasurementWithSpeed。

我可以只返回函数 sensorUpdateValues 中的三个值,而不是将它们存储到新变量中吗?

最佳答案

解决此问题的更好方法是将传感器对象传递给 prepare(forSegue:) 中的 InfoTableViewController,然后在 InfoTableViewController 中您可以调用 sensor.lastMeasurement.speedInMetersPerSecond 或其中的任何其他 var。由于该类是通过引用传递的,因此即使您转换到新的 ViewController,它也会保留数据。

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let infoVC = segue.destination as? InfoTableViewController {
infoVC.sensor = self.sensor
}
if segue.identifier == Constants.ScanSegue {

// Scan segue
bluetoothManager.startScan()
scanViewController = (segue.destination as? UINavigationController)?.viewControllers.first as? ScanViewController
}

}然后你当然可以在新的 VC 中用这些数据做任何你想做的事情(将值分配给标签或诸如此类的东西)

关于ios - 无法在 swift 3 的结构中获取返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47641366/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com