使用 CoreMotion 框架,我们可以很方便地获取设备各种传感器的数据(比如:加速器、陀螺仪、磁力计)。上文中我介绍了陀螺仪(点击查看),本文接着讲解如何获取磁力计相关数据。
一、相关说明
1 磁力计介绍
磁力计(又叫磁力传感器、磁力仪、磁场计、磁强计),它可以用来感应周边的磁场情况。
其获取的数据包含三轴磁力值。
iPad的盒盖锁屏功能就是通过磁力计实现。同时它可以感应地球磁场, 获得方向信息, 使位置服务数据更精准,常用于电子罗盘和导航应用。
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 getMagnetometerData(_ sender: Any) {
//判断设备支持情况
guard motionManager.isMagnetometerAvailable else {
self.textView.text = "\n当前设备不支持磁力计\n"
return
}
//获取数据
self.motionManager.startMagnetometerUpdates()
if let magnetometerData = self.motionManager.magnetometerData {
let magneticField = magnetometerData.magneticField
var text = "---当前磁力计数据---\n"
text += "x: \(magneticField.x)\n"
text += "y: \(magneticField.y)\n"
text += "z: \(magneticField.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()
//开始磁力计更新
startMagnetometerUpdates()
}
// 开始获取磁力计数据
func startMagnetometerUpdates() {
//判断设备支持情况
guard motionManager.isMagnetometerAvailable else {
self.textView.text = "\n当前设备不支持磁力计\n"
return
}
//设置刷新时间间隔
self.motionManager.magnetometerUpdateInterval = self.timeInterval
//开始实时获取数据
let queue = OperationQueue.current
self.motionManager.startMagnetometerUpdates(to: queue!, withHandler: {
(magnetometerData, error) in
guard error == nil else {
print(error!)
return
}
// 有更新
if self.motionManager.isMagnetometerActive {
if let magneticField = magnetometerData?.magneticField {
var text = "---当前磁力计数据---\n"
text += "x: \(magneticField.x)\n"
text += "y: \(magneticField.y)\n"
text += "z: \(magneticField.z)\n"
self.textView.text = text
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}