使用 CoreMotion 框架,我们可以很方便地获取设备各种传感器的数据(比如:加速器、陀螺仪、磁力计)。关于加速器之前已经写过相关文章了(Swift – 加速传感器(CoreMotion)的用法),本文讲讲如何获取陀螺仪(螺旋仪)相关数据。
一、陀螺仪介绍
通过陀螺仪我们能够感知设备的握持方式,这个在一些赛车类的游戏中常常会用到。 陀螺仪与加速计的区别在于:在静止时,陀螺仪的每个轴的数据都为 0。但是加速计则根据手机的摆放位置,xyz 的每个轴的数也会不一样。
1 x、y、z轴
加速器和陀螺仪数据以 iOS 设备上 3 维坐标来展示。
- (1)对于 iphone 手机来说,画面上下为 y 轴,左右为 x 轴,贯穿屏幕为 z 轴。
- (2)向上,向右,手机的前面分别是各轴的正方向。
包含下面四种数据:
attitude
(类型:CMAttitude)- 返回设备的方位信息,包含roll 、pitch、yaw三个欧拉角的值
roll
: 设备绕 Z 轴转过的角度pitch
: 设备绕 X 轴转过的角度yaw
: 设备绕 Y 轴转过的角度
rotationRate
(类型:CMRotationRate)- 经过滤波操作之后的陀螺仪数据,即 静止时,三个方向的转动速度接近于0;
gravity
(类型:CMAcceleration)- 返回重力对设备在三个方向上的加速度
- 即重力加速度矢量在当前设备的参考坐标系中的表达,开发中不再需要通过滤波来提取这个信息
userAcceleration
(类型:CMAcceleration)- 返回用户对设备在三个方向上的加速度
- 不再需要滤波,但根据程序需求而加的滤波算法可以保留
2 CMMotionManager类
(1)通过 CMMotionManager 类我们可以获取到加速器,陀螺仪,磁力仪,传感器这4类数据,同时它们的接口是一致的。
(2)CMMotionManager 同时提供了”拉“和”推“两种方式的获取方式。二者区别如下:
- 通过获取当前任何传感器的状态或者 CoreMotionManager 的只读属性组合数据来“拉”动态数据。
- 通过 block 闭包在特定的时间间隔来获取我们想要的更新数据集合来捕获“推”数据。
二、使用样例
1 需要的时候才去采集数据
(1)效果图 这个便是前面讲的拉数据(pull)。我们每次点击“获取数据”按钮后,便去取当前陀螺仪的数据并显示出来。
(2)样例代码
import UIKit import CoreMotion class ViewController: UIViewController { //用于显示数据信息 @IBOutlet weak var textView: UITextView! //运动管理器 let motionManager = CMMotionManager() override func viewDidLoad() { super.viewDidLoad() } //点击获取当前陀螺仪数据 @IBAction func getGyroData(_ sender: Any) { //判断设备支持情况 guard motionManager.isGyroAvailable else { self.textView.text = "\n当前设备不支持陀螺仪\n" return } //获取数据 self.motionManager.startGyroUpdates() if let gyroData = self.motionManager.gyroData { let rotationRate = gyroData.rotationRate var text = "---当前陀螺仪数据---\n" text += "x: \(rotationRate.x)\n" text += "y: \(rotationRate.y)\n" text += "z: \(rotationRate.z)\n" self.textView.text = text } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
2 实时采集所有数据
(1)效果图
这个便是前面讲的推数据(push)。根据我们设置的采集频率(通知频率)来不断地获取最新数据。
(2)样例代码
import UIKit import CoreMotion class ViewController: UIViewController { //用于显示实时信息 @IBOutlet weak var textView: UITextView! //运动管理器 let motionManager = CMMotionManager() //刷新时间间隔 let timeInterval: TimeInterval = 0.2 override func viewDidLoad() { super.viewDidLoad() //开始陀螺仪更新 startGyroUpdates() } // 开始获取陀螺仪数据 func startGyroUpdates() { //判断设备支持情况 guard motionManager.isGyroAvailable else { self.textView.text = "\n当前设备不支持陀螺仪\n" return } //设置刷新时间间隔 self.motionManager.gyroUpdateInterval = self.timeInterval //开始实时获取数据 let queue = OperationQueue.current self.motionManager.startGyroUpdates(to: queue!, withHandler: { (gyroData, error) in guard error == nil else { print(error!) return } // 有更新 if self.motionManager.isGyroActive { if let rotationRate = gyroData?.rotationRate { var text = "---当前陀螺仪数据---\n" text += "x: \(rotationRate.x)\n" text += "y: \(rotationRate.y)\n" text += "z: \(rotationRate.z)\n" self.textView.text = text } } }) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }