Swift陀螺仪的偏航、俯仰、横滚。

4
我正在为我的编程课程做一个项目,使用Xcode中的Swift语言。我想创建一个使用陀螺仪的应用程序,但由于我不知道如何解决Xcode中的一些错误,因此无法在我的iPhone上运行它。当我运行程序时,会显示“fatal error: unexpectedly found nil while unwrapping an Optional value(lldb)”。 我的项目主要目的是在iPhone屏幕上显示旋转(偏航角、俯仰角和翻滚角)的度数,并利用陀螺仪进行测量。如果有人能帮助我解决这个问题,我将非常感激。谢谢您提前的帮助。
我的ViewController中的代码:
import UIKit
import CoreMotion

class ViewController: UIViewController {

    var currentMaxRotX: Double = 0.0
    var currentMaxRotY: Double = 0.0
    var currentMaxRotZ: Double = 0.0

    let motionManager = CMMotionManager()

    @IBOutlet var rotX : UILabel! = nil
    @IBOutlet var rotY : UILabel! = nil
    @IBOutlet var rotZ : UILabel! = nil

    @IBOutlet var maxRotX : UILabel! = nil
    @IBOutlet var maxRotY : UILabel! = nil
    @IBOutlet var maxRotZ : UILabel! = nil


    @IBOutlet weak var RollLabel: UILabel! = nil

    @IBOutlet weak var PitchLabel: UILabel! = nil

    @IBOutlet weak var YawLabel: UILabel! = nil

    override func viewDidLoad() {

        if motionManager.gyroAvailable {

            if !motionManager.gyroActive {
                motionManager.gyroUpdateInterval = 0.2
                motionManager.startGyroUpdates()
                //motionManager = [[CMMotionManager alloc]init]; should I use this ???
                //motionManager.deviceMotionUpdateInterval = 0.2;
                //motionManager.startDeviceMotionUpdates()

                 motionManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue(), withHandler: {(gyroData: CMGyroData!, error: NSError!)in
                     self.outputRotationData(gyroData.rotationRate)
                     if (error != nil)
                     {
                         println("\(error)")
                     }
                 })      
            }
       } else {
              var alert = UIAlertController(title: "No gyro", message: "Get a Gyro", preferredStyle: UIAlertControllerStyle.Alert)
              alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
              self.presentViewController(alert, animated: true, completion: nil)
    }


     super.viewDidLoad()
    }

    // radians to degrees
    func radians(fromDegrees degrees: Double) -> Double {
        return 180 * degrees / M_PI
    }

    func outputRotationData(rotation:CMRotationRate)
    {
        rotX.text = NSString(format:"Rotation X: %.4f",rotation.x)
        if fabs(rotation.x) > fabs(currentMaxRotX)
        {
            currentMaxRotX = rotation.x
        }

        rotY.text = NSString(format:"Rotation Y: %.4f", rotation.y)
        if fabs(rotation.y) > fabs(currentMaxRotY)
        {
            currentMaxRotY = rotation.y
        }
        rotZ.text = NSString(format:"Rotation Z:%.4f", rotation.z)
        if fabs(rotation.z) > fabs(currentMaxRotZ)
        {
            currentMaxRotZ = rotation.z
        }

        maxRotX.text = NSString(format:"Max rotation X: %.4f", currentMaxRotX)
        maxRotY.text = NSString(format:"Max rotation Y:%.4f", currentMaxRotY)
        maxRotZ.text = NSString(format:"Max rotation Z:%.4f", currentMaxRotZ)

        var attitude = CMAttitude()
        var motion = CMDeviceMotion()
        motion = motionManager.deviceMotion
        attitude = motion.attitude


        YawLabel.text = NSString (format: "Yaw: %.2f", attitude.yaw)    //radians to degress NOT WORKING
        PitchLabel.text = NSString (format: "Pitch: %.2f", attitude.pitch)//radians to degress NOT WORKING
        RollLabel.text = NSString (format: "Roll: %.2f", attitude.roll)//radians to degress NOT WORKING
      }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

这篇文章应该是你所需要的:https://dev59.com/H2Af5IYBdhLWcg3wcyar - Alex Brown
你能具体一点吗,因为我是初学者。我不知道错误在哪里或者我的代码中哪个值为空。谢谢。 - Moonwalker4z
2个回答

10

这两行代码使用了隐式解包可选类型:你在使用它们时不需要添加?!,但如果它们为nil,就会导致程序崩溃。在这种情况下,motionManager.deviceMotionnil,因为你在访问之前没有调用motionManager.startDeviceMotionUpdates()

你应该在viewDidLoad方法中执行这个操作:

override func viewDidLoad() {

    if motionManager.gyroAvailable {
        motionManager.deviceMotionUpdateInterval = 0.2;
        motionManager.startDeviceMotionUpdates()

        motionManager.gyroUpdateInterval = 0.2
        motionManager.startGyroUpdatesToQueue(NSOperationQueue.currentQueue()) {
           [weak self] (gyroData: CMGyroData!, error: NSError!) in

           self?.outputRotationData(gyroData.rotationRate)
           if error != nil {
               println("\(error)")
           }
        }
    } else {
        // alert message
    }

    super.viewDidLoad()
}

以下是一些额外的更改:

  1. 在调用 startGyroUpdatesToQueue() 之前,无需调用 startGyroUpdates()
  2. Swift 对于像这个完成处理程序一样的 尾随闭包 - 更容易编写和阅读。
  3. 为了避免引用循环,在完成处理程序内将 self 声明为 weak - 这需要在访问 self 时使用可选链接。

1

“guard”、“if let”和可选链是安全地解包可选项的关键,这里是Swift4的答案:

let motionManager = CMMotionManager()
    override func viewDidLoad() {
        if motionManager.isGyroAvailable {
            motionManager.deviceMotionUpdateInterval = 0.2;
            motionManager.startDeviceMotionUpdates()

            motionManager.gyroUpdateInterval = 0.2
            guard let currentQueue = OperationQueue.current else { return }
            motionManager.startGyroUpdates(to: currentQueue) { (gyroData, error) in

                // Do Something, call function, etc
                if let rotation = gyroData?.rotationRate {
                    print(rotation)
                    print(rotation.x)
                    print(rotation.y)
                    print(rotation.z)
                }

                if error != nil {
                    print("\(error)")
                }
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接