Swift陀螺仪偏航,俯仰,滚动

时间:2015-01-05 16:24:21

标签: ios iphone xcode swift core-motion

我正在为我的学校做一个项目,为一个编程主题。我在Swift的Xcode工作。我想制作一个使用陀螺仪的应用程序。我不知道但不知何故它不会在我的iphone上运行因为Xcode中的一些错误我不知道如何修复。当我运行该程序时说“致命错误:在解开一个Optional值时意外发现nil (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.
    }
}

2 个答案:

答案 0 :(得分:9)

在这两行中,您正在使用隐式解包的选项:您在没有?!的情况下使用它们,但如果它们重新{{{}},它们会导致您的程序崩溃{1}}。在这种情况下,nilmotionManager.deviceMotion,因为您在访问之前尚未调用nil

您的motionManager.startDeviceMotionUpdates()方法是执行此操作的正确位置:

viewDidLoad

还有一些额外的变化:

  1. 您不需要在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() } 之前致电startGyroUpdates()
  2. Swift使用trailing closures作为这样的完成处理程序 - 更好地编写和阅读。
  3. 要避免引用周期,请在完成处理程序中将startGyroUpdatesToQueue()声明为self - 这需要在访问weak时使用可选链接。

答案 1 :(得分:0)

"警卫","如果让"和可选链接是安全解包选项的关键,这里有一个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)")
                }
            }
        }
    }