iOS 传感器编程 iOS 手势处理 AddressBook联系人管理 iOS 传感器编程 内容概述 传感器编程的准备工作 加速度传感器(Accelerometer) 陀螺仪传感器(Gyroscope) 磁力传感器(Magnetometer) 设备移动(Device motion) 通过加速度传感器控制小球运动 设备传感器使我们的程序变得更加生动有趣,尤其体现在游戏开发中,例如,一些飞车类游戏可通过设备传感器来控制方向。iOS SDK 中提供了四种设备传感器,他们分别是,加速度传感器(Accelerometer)、陀螺仪(Gyroscope)、磁力传感器(Magnetometer)和设备移动传感器(Device motion)。传感器编程API框架是CoreMotion.framework,使用时必须添加该框架。传感器编程的核心类是CMMotionManager,可以调用startXXX和stopXXX方法对不同传感器开始更新和停止更新。 下面是本章核心类一览: 表1.1 本章核心类一览 类名称 类说明 CMMotionManager 传感器管理类,用来启动和停止服务及获得当前传感器数据 CMAccelerometerData 加速度传感器数据封装类 CMAcceleration 是CMAccelerometerData的一个属性,类型是一个结构体,用x、y、z三个变量表示三个方向的重力加速度 CMMagnetometerData 磁力传感器数据封装类 CMMagneticField 是CMMagnetometerData的一个属性,类型是一个结构体,用x、y、z三个变量表示三个方向的磁力 CMGyroData 陀螺仪数据封装类 CMRotationRate 是CMGyroData的一个属性,类型是一个结构体,用x、y、z三个变量表示三个方向的角速度旋转量 CMDeviceMotion 检测设备移动的属性的封装类,可以测量设备的加速度,角速度和设备当前姿势等 CMAttitude 设备当前方向的测量值,分别使用roll、pitch和yaw来表示设备的旋转量、左右倾斜量和上下偏移量 1.1 传感器编程的准备工作 传感器编程的首要任务是添加CoreMotion.framework到项目中,并添加头文件到当前项目。另外,我们需要检测当前传感器是否可利用,是否被激活。下面的案例用来检测传感器是否可利用、是否被激活。实现步骤如下: 创建项目,并添加CoreMotion.framework到项目中。 在界面添加一个按钮,并添加点击事件方法,并声明CMMotionManager属性。 #import <UIKit/UIKit.h> #import <CoreMotion/CoreMotion.h> @interface AmakerViewController : UIViewController @property(nonatomic,strong)CMMotionManager *mm; - (IBAction)check:(id)sender; @end 在viewDidLoad方法中实例化CMMotionManager。 - (void)viewDidLoad { [super viewDidLoad]; self.mm = [[CMMotionManager alloc]init]; } 按钮单击事件方法实现。 - (IBAction)check:(id)sender { // 检测重力加速度传感器是否可利用,已经激活 if (self.mm.isAccelerometerAvailable) { NSLog(@"Accelerometer Available..."); if (self.mm.isAccelerometerActive) { NSLog(@"Accelerometer Active..."); }else{ NSLog(@"Accelerometer not Active..."); } }else{ NSLog(@"Accelerometer not Available..."); } // 检测陀螺仪传感器是否可利用,已经激活 if (self.mm.isGyroAvailable) { NSLog(@"Gyro Available..."); if (self.mm.isGyroActive) { NSLog(@"Gyro Active..."); }else{ NSLog(@"Gyro not Active..."); } }else{ NSLog(@"Gyro not Available..."); } // 检测磁力传感器是否可利用,已经激活 if (self.mm.isMagnetometerAvailable) { NSLog(@"Magnetometer Available..."); if (self.mm.isMagnetometerActive) { NSLog(@"Magnetometer Active..."); }else{ NSLog(@"Magnetometer not Active..."); } }else{ NSLog(@"Magnetometer not Available..."); } // 检测设备移动传感器是否可利用,已经激活 if (self.mm.isDeviceMotionAvailable) { NSLog(@"DeviceMotion Available..."); if (self.mm.isDeviceMotionActive) { NSLog(@"DeviceMotion Active..."); }else{ NSLog(@"DeviceMotion not Active..."); } }else{ NSLog(@"DeviceMotion not Available..."); } } 程序运行结果如下所示。 1.2 加速度传感器(Accelerometer) 通过减速度传感,可以获得设备当前x、y、z轴三个方向的加速度坐标值,坐标系统如下图所示。 下面我们通过一个实例来演示加速度传感器的用法,该案例在界面上添加两个按钮分别开启和停止当前传感器,一个UILabel来显示三个方向上的加速度值。实现步骤如下所示: 创建一个项目添加CoreMotion.framework框架。 在界面上添加两个按钮和一个UILabel标签,为按钮创建点击事件方法,为标签添加属性,并声明CMMotionManager属性。 #import <UIKit/UIKit.h> #import <CoreMotion/CoreMotion.h> @interface AmakerViewController : UIViewController // 开启方法 - (IBAction)start:(id)sender; // 停止方法 - (IBAction)stop:(id)sender; // 显示坐标数据的标签 @property (strong, nonatomic) IBOutlet UILabel *myData; // 移动管理器 @property(strong,nonatomic) CMMotionManager *mm; @end 在viewDidLoad方法中,实例化CMMotionManager - (void)viewDidLoad { [super viewDidLoad]; // 实例化CMMotionManager self.mm = [[CMMotionManager alloc]init]; } 在开启方法中开启传感器服务,在Block方法中获得当前传感器数据。 - (IBAction)start:(id)sender { // 检测传感器是否可利用 if (self.mm.isAccelerometerAvailable) { // 实例化操作队列 NSOperationQueue *queue = [[NSOperationQueue alloc]init]; // 开启传感器服务,在Block方法中获得当前传感器数据 [self.mm startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { // 属性 CMAcceleration data = accelerometerData.acceleration; // 三个坐标值 double x = data.x; double y = data.y; double z = data.z; // NSLog打印 NSString *str = [NSString stringWithFormat:@"[%f,%f,%f]",x,y,z]; NSLog(@"%@",str); // 使用UILabel显示 dispatch\_async(dispatch\_get\_main\_queue(), ^{ self.myData.text = str; }); }]; }else{ NSLog(@"Accelerometer not Available"); } } 在停止方法中停止传感器。 - (IBAction)stop:(id)sender { // 停止传感器 if (self.mm.isAccelerometerAvailable) { [self.mm stopAccelerometerUpdates]; }else{ NSLog(@"Accelerometer not Available"); } } 程序运行结果如下图所示。 1.3 陀螺仪传感器(Gyroscope) 陀螺仪传感器,也称为角速度传感器,是测量设备在x、y、z三个方向上的旋转角度的,旋转坐标系统如下图所示。 下面我们也是通过一个实例来演示如何获得,陀螺仪传感器角速度数据,该实例在界面上添加两个按钮来开启和停止陀螺仪传感器,使用NSLog打印数据。实现步骤如下所示。 创建项目并添加CoreMotion.framework框架。 在界面上添加两个按钮,并添加点击事件方法,声明CMMotionManager属性。 #import <UIKit/UIKit.h> #import <CoreMotion/CoreMotion.h> @interface AmakerViewController : UIViewController // 开启方法 - (IBAction)start:(id)sender; // 停止方法 - (IBAction)stop:(id)sender; // 显示数据信息 @property (strong, nonatomic) IBOutlet UILabel *myLabel; // 移动管理器属性 @property (strong,nonatomic) CMMotionManager *mm; @end 在viewDidLoad方法中实例化CMMotionManager。 - (void)viewDidLoad { [super viewDidLoad]; // 实例化CMMotionManager self.mm = [[CMMotionManager alloc]init]; } 在start方法中开启传感器并获得数据。 - (IBAction)start:(id)sender { if (self.mm.isGyroAvailable) { // 开启传感器 [self.mm startGyroUpdatesToQueue:[[NSOperationQueue alloc]init] withHandler:^(CMGyroData *gyroData, NSError *error) { // 获得角速度数据 CMRotationRate data = gyroData.rotationRate; double x = data.x; double y = data.y; double z = data.z; // 打印输出 NSString *str = [NSString stringWithFormat:@"[%f,%f,%f]",x,y,z]; NSLog(@"%@",str); // 在标签上显示 dispatch\_async(dispatch\_get\_main\_queue(), ^{ self.myLabel.text = str; }); }]; } } 在stop方法中停止传感器。 - (IBAction)stop:(id)sender { // 停止传感器 if (self.mm.isGyroAvailable) { [self.mm stopGyroUpdates]; } } 程序运行结果如下图所示。 1.4 磁力传感器(Magnetometer) 磁力传感器可以检测当前设备周围磁场强度值,磁力传感器的典型应用是指南针,下面通过案例还是演示如何获得磁力传感器x、y、z三个坐标轴方向的磁场数据,实现步骤如下所示。 创建项目并添加CoreMotion.framework框架。 在界面上添加两个按钮和一个UILabel。 在.h文件中声明两个点击事件方法和CMMotionManager属性和UILabel属性。 #import <UIKit/UIKit.h> #import <CoreMotion/CoreMotion.h> @interface AmakerViewController : UIViewController // 开启 - (IBAction)start:(id)sender; // 停止 - (IBAction)stop:(id)sender; // 移动管理器 @property(nonatomic,strong)CMMotionManager *mm; // 显示当前数据信息 @property (strong, nonatomic) IBOutlet UILabel *myLabel; @end 在viewDidLoad方法中实例化CMMotionManager。 - (void)viewDidLoad { [super viewDidLoad]; // 实例化CMMotionManager self.mm = [[CMMotionManager alloc]init]; } 在按钮的开启事件方法中开启磁力传感器,并获取数据。 - (IBAction)start:(id)sender { if (self.mm.isMagnetometerAvailable) { // 开启 [self.mm startMagnetometerUpdatesToQueue:[[NSOperationQueue alloc]init] withHandler:^(CMMagnetometerData *magnetometerData, NSError *error) { // 获取实时数据 CMMagneticField data = magnetometerData.magneticField; double x = data.x; double y = data.y; double z = data.z; // 打印数据 NSString *str = [NSString stringWithFormat:@"[%f,%f,%f]",x,y,z]; NSLog(@"%@",str); // 在UILabel上显示数据 dispatch\_async(dispatch\_get\_main\_queue(), ^{ self.myLabel.text = str; }); }]; } } 在按钮的停止事件方法中停止磁力传感器。 - (IBAction)stop:(id)sender { if (self.mm.isMagnetometerAvailable) { [self.mm stopMagnetometerUpdates]; } } 程序运行结果如下图所示。 1.5 设备移动(Device motion) 如果设备有加速度传感器和角速度传感器,那么通过这个两个传感器可以检测出当前设备的运动情况,并获得运动数据。获得设备移动数据方法和获得其他传感器数据的方法一致,下面我们通过实例来演示如何获得移动数据。操作步骤如下所示: 创建项目并添加CoreMotion.framework框架。 在界面上添加两个按钮和一个UILabel标签。 在.h文件中声明两个按钮的事件方法,并声明标签属性和CMMotionManager属性。 #import <UIKit/UIKit.h> #import <CoreMotion/CoreMotion.h> @interface AmakerViewController : UIViewController // 开启方法 - (IBAction)start:(id)sender; // 停止方法 - (IBAction)stop:(id)sender; // UILabel 属性 @property (strong, nonatomic) IBOutlet UILabel *myLabel; // CMMotionManager属性 @property(strong,nonatomic) CMMotionManager *mm; @end 在viewDidLoad方法中实例化CMMotionManager。 - (void)viewDidLoad { [super viewDidLoad]; // 实例化CMMotionManager self.mm = [[CMMotionManager alloc]init]; // 更新频率 self.mm.deviceMotionUpdateInterval= 1; } 在开启按钮事件方法中开启,并获得数据。 - (IBAction)start:(id)sender { if (self.mm.isDeviceMotionAvailable) { // 开启 [self.mm startDeviceMotionUpdatesToQueue:[[NSOperationQueue alloc]init] withHandler:^(CMDeviceMotion *motion, NSError *error) { // 获得数据 CMAttitude *attr = motion.attitude; double roll = attr.roll; double pitch = attr.pitch; double raw = attr.yaw; // 打印数据 NSString *str = [NSString stringWithFormat:@"[%f,%f,%f]",roll,pitch,raw]; NSLog(@"str = %@",str); // 显示数据 dispatch\_async(dispatch\_get\_main\_queue(), ^{ self.myLabel.text = str; }); }]; } } 在停止按钮事件方法中停止。 - (IBAction)stop:(id)sender { if (self.mm.isDeviceMotionAvailable) { [self.mm stopDeviceMotionUpdates]; } } 程序运行结果如下图所示。 1.6 通过加速度传感器控制小球运动 本节通过加速度传感器小球运动的游戏模型,该案例首先获得加速度传感器x、y坐标数值,通过该数值动态改变小球图片的frame属性的x、y坐标。实现步骤如下所示: 创建项目,并添加CoreMotion.framework框架。 在界面上添加UIImageView和UIButton。 在.h文件中添加按钮点击事件方法、图片属性和CMMotionManager属性。 #import <CoreMotion/CoreMotion.h> @interface AmakerViewController : UIViewController // CMMotionManager属性 @property(nonatomic,strong)CMMotionManager *mm; // 图片属性 @property (strong, nonatomic) IBOutlet UIImageView *img; // 点击方法 - (IBAction)start:(id)sender; @end 在viewDidLoad方法中实例化CMMotionManager。 - (void)viewDidLoad { [super viewDidLoad]; self.mm = [[CMMotionManager alloc]init]; //self.mm.accelerometerUpdateInterval=0.2; } 在按钮的点击方法中,开启加速度传感器,异步获取数据,并更新图片的frame属性。 - (IBAction)start:(id)sender { // 开启加速度传感器,异步获取数据 [self.mm startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { dispatch\_sync(dispatch\_get\_main\_queue(), ^(void) { // 获得当前图片的frame属性 CGRect imgFrame = self.img.frame; // 将当前传感器x属性赋值给图片x imgFrame.origin.x += accelerometerData.acceleration.x; // 判断图片是否x越界 if(!CGRectContainsRect(self.view.bounds, imgFrame)) // 如果x越界不变 imgFrame.origin.x = self.img.frame.origin.x; // 将当前传感器y属性赋值给图片y imgFrame.origin.y -= accelerometerData.acceleration.y; // 判断图片是否y越界 if(!CGRectContainsRect(self.view.bounds, imgFrame)) // 如果y越界不变 imgFrame.origin.y = self.img.frame.origin.y; // 更改frame属性 self.img.frame = imgFrame; }); }]; } 程序运行结果如下图所示。 iOS 手势处理 AddressBook联系人管理