首页 > 解决方案 > Swift/iOS - 如何使用一个范围/函数中的值并将其传递给另一个?

问题描述

我试图将 gyroX 的值传递给另一个函数,但是当我在另一个函数中将它用作 gyroX 时,它最终的值为 0。

这是代码:

var gyroX = Float()
        
motion.startGyroUpdates(to: .main) { (data, error) in
    if let myData = data {
        gyroX = Float(myData.rotationRate.x)
    }
}

标签: iosswift

解决方案


使用 Xcode 13 Beta 和 Swift 5.5

这是我们现在可以通过 Async/Await 的 Continuations 解决的问题

我们将首先创建一个函数,将回调转换为可等待的结果,例如:

func getXRotation(from motion: CMMotionManager) async throws -> Float {
    try await withCheckedThrowingContinuation { continuation in
        class GyroUpdateFailure: Error {} // make error to throw
        motion.startGyroUpdates(to: .main) { (data, error) in
            if let myData = data {
                continuation.resume(returning:  Float(myData.rotationRate.x))
            } else {
                throw GyroUpdateFailure()
            }
        }
    }
}

然后我们可以分配变量并像这样使用它:

let gyroX = try await getXRotation(from: motion)
callSomeOtherFunction(with: gyroX)

使用 Xcode <= 12 并结合

在当前版本的 Swift 和 Xcode 中,我们可以使用 Combine 框架使回调处理对我们来说更容易一些。首先,我们将运动管理器的闭包转换为“Future”。然后我们可以在联合链中使用这个未来。


func getXRotation(from motion: CMMotionManager) -> Future<CMGyroData, Error> {
    Future { promise in
        class GyroUpdateFailure: Error {} // make error to throw
        motion.startGyroUpdates(to: .main) { (data, error) in
            if let myData = data {
                promise(.success(myData))
            } else {
                promise(.failure(GyroUpdateFailure()))
            }
        }
    }
}

// This is the other function you want to call
func someOtherFunction(_ x: Float) {}

// Then we can use it like so
_ = getXRotation(from: motion)
    .eraseToAnyPublisher()
    .map { Float($0.rotationRate.x) }
    .map(someOtherFunction)
    .sink { completion in
        switch completion {
        case .failure(let error):
            print(error.localizedDescription)
        default: break
        }
    } receiveValue: {
        print($0)
    }


合并流程有一些重要的部分。就是其中_ =之一。在发布者上“下沉”的结果是一个“可取消”的对象。如果我们不将其存储在局部变量中,系统可以在任务执行之前清理任务。所以你肯定会想要这样做。

我强烈建议您查看 SwiftBySundell.com 以了解更多关于 Combine 或 Async/Await 和 RayWenderlich.com 的一般移动开发信息。


推荐阅读