加速计

● 加速计的作用
● 用于检测设备的运动(比如摇晃)

● 加速计的经典应用场景

● 摇一摇
● 计步器

● 加速计程序的开发
● 在iOS4以前:使用UIAccelerometer,用法非常简单(到了iOS5就已经过期)

● 从iOS4开始:CoreMotion.framework

● 虽然UIAccelerometer已经过期,但由于其用法极其简单,很多程序里面都
还有残留

UIAccelerometer的使用步骤
● 获得单例对象
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];

● 设置代理
accelerometer.delegate = self;

● 设置采样间隔
accelerometer.updateInterval = 1.0/30.0; // 1秒钟采样30次

● 实现代理方法
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:

(UIAcceleration *)acceleration
// acceleration中的x、y、z三个属性分别代表每个轴上的加速度

#import "ViewController.h"
#import "UIView+Extension.h" @interface ViewController ()<UIAccelerometerDelegate>
/**
* 小球
*/
@property (weak, nonatomic) IBOutlet UIImageView *imageBall;
/**
* 保存速度
*/
@property (nonatomic, assign) CGPoint velocity;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. // 1.利用单利获取采集对象
UIAccelerometer *acc = [UIAccelerometer sharedAccelerometer];
// 2.设置代理
acc.delegate = self;
// 3.设置采样时间
acc.updateInterval = / ; }
#pragma mark -UIAccelerometerDelegate
// 4.实现代理方法
/**
* 只要采集到数据就会调用(调用频率非常高)
*
* @param accelerometer 触发事件的对象
* @param acceleration 获取到得数据
*/
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
NSLog(@"x = %f / y = %f / z = %f", acceleration.x, acceleration.y, acceleration.z); /*
速度 = 加速度 * 时间
V = at; == a * t1 + a * t2 + a * t3 ....;
*/
// 不能直接修改对象的结构体属性的成员
// self.velocity.x += acceleration.x;
_velocity.x += acceleration.x;
// -=的原因是因为获取到得Y轴的加速度和UIKit的坐标系的Y的值是相反的, 而我们将来想让小球往加速度的反方向运动, 所以 -=;
_velocity.y -= acceleration.y; /* 移动的距离 = 速度 * 时间
S = vt; == v * t1 + v * t2 + v * t3 ....;
*/
self.imageBall.x += _velocity.x;
self.imageBall.y += _velocity.y; // 边界检测
if (self.imageBall.x <= ) {
// 矫正小球当前的位置
self.imageBall.x = ;
// 超出了屏幕的左边
_velocity.x *= -0.5;
}
if (self.imageBall.y <= ) {
// 矫正小球当前的位置
self.imageBall.y = ;
// 超出屏幕的顶部
_velocity.y *= -0.5;
} if (CGRectGetMaxY(self.imageBall.frame) >= self.view.height) {
// 矫正小球当前的位置
self.imageBall.y = self.view.height - self.imageBall.height;
// 查出屏幕的底部
_velocity.y *= -0.5;
} if (CGRectGetMaxX(self.imageBall.frame) >= self.view.width) {
// 矫正小球当前的位置
self.imageBall.x = self.view.width - self.imageBall.width;
// 查出屏幕的右边
_velocity.x *= -0.5;
} }
@end
/*
> 加速计
*PPT介绍加速计, 加速计属于传感器的范畴...
*新建项目讲解加速计的传统使用
*查看Accelerometer头文件, 讲解Accelerometer头文件中的属性引出为什么过时了还那么多人用(简单, 查看头文件)
*从代理方法参数引出定义属性保存小球加速度(CGPoint), 并在代理方法中设置小球的位置
*Vt = V0 + a * t (最终速度 = 初始速度 + 加速度 * 时间)
Vt = V0 + g * t (加速度是恒定的9.8)
Vt = V0 + g1 + g2 + g3 … (时间和加速度都是恒定的)
Vt = V0 + a1 + a2 + a3 … (手机中时间是恒定的, 加速度不是恒定的)
*从小球移除频幕看不到引出画图讲解边界检测(碰撞检测)
*从小球会贴在边框出不来引出画图讲解如何解决(移动小球的位置到边界再加速度)
*讲解为什么用两个if 不用else if, 小球在四个角的情况
*/ #import "CZViewController.h" @interface CZViewController ()<UIAccelerometerDelegate>
/**
* 小球
*/
@property (nonatomic, weak)UIImageView *ballIv;
/**
* 保存x y方向加速度
*/
@property (nonatomic, assign)CGPoint ballVelocity; @end @implementation CZViewController - (void)viewDidLoad
{
[super viewDidLoad]; // 1.添加小球
UIImage *image = [UIImage imageNamed:@"black"];
UIImageView *iv = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:iv];
self.ballIv = iv; // 2.获得加速计单例
/**
updateInterval 更新间隔(采样,采集数据样本)
delegate 代理
*/
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
// 设置采样时间
accelerometer.updateInterval = / 30.0;
// 设置代理
accelerometer.delegate = self;
} #pragma mark - UIAccelerometerDelegate
// UIAcceleration 加速度
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
// 1. 记录小球加速度
_ballVelocity.x += acceleration.x;
// 加速计y轴方向和UIKit坐标相反
_ballVelocity.y -= acceleration.y; // 2.更新小球位置
[self updateLocation];
} - (void)updateLocation
{
// 设置小球的位置
CGPoint center = self.ballIv.center;
CGSize size = self.view.bounds.size; // 解决小球出界问题,碰撞检测
// 水平方向:左边,右边
if (CGRectGetMinX(self.ballIv.frame) <= || CGRectGetMaxX(self.ballIv.frame) >= size.width) {
// 修改小球的速度方向
_ballVelocity.x *= -; // 修复位置 < 0
if (CGRectGetMinX(self.ballIv.frame) <= ) {
center.x = self.ballIv.bounds.size.width / 2.0;
} else {
center.x = size.width - self.ballIv.bounds.size.width / 2.0;
}
} // 垂直方向
if (CGRectGetMinY(self.ballIv.frame) <= || CGRectGetMaxY(self.ballIv.frame) >= size.height) {
// 修改小球的速度方向
_ballVelocity.y *= -; // 修复位置 < 0
if (CGRectGetMinY(self.ballIv.frame) <= ) {
center.y = self.ballIv.bounds.size.height / 2.0;
} else {
center.y = size.height - self.ballIv.bounds.size.height / 2.0;
}
} center.x += _ballVelocity.x;
center.y += _ballVelocity.y; self.ballIv.center = center;
} @end
Core Motion(iPhone4)

苹果特地在iOS4中增加了专门处理Motion的框架-CoreMotion.framework

Core Motion获取数据的两种方式

● push
● 实时采集所有数据(采集频率高)

● pull
● 在有需要的时候,再主动去采集数据

Core Motion的使用步骤(push)

● 创建运动管理者对象
CMMotionManager *mgr = [[CMMotionManager alloc] init];

● 判断加速计是否可用(最好判断)
if (mgr.isAccelerometerAvailable) {

// 加速计可用
}

● 设置采样间隔
mgr.accelerometerUpdateInterval = 1.0/30.0; // 1秒钟采样30次

● 开始采样(采样到数据就会调用handler,handler会在queue中执行)
- (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue

withHandler:(CMAccelerometerHandler)handler;
Core Motion的使用步骤(pull)

● 创建运动管理者对象

CMMotionManager *mgr = [[CMMotionManager alloc] init];

● 判断加速计是否可用(最好判断)
if (mgr.isAccelerometerAvailable) { // 加速计可用 }

● 开始采样
- (void)startAccelerometerUpdates;

● 在需要的时候采集加速度数据
CMAcceleration acc = mgr.accelerometerData.acceleration;
NSLog(@"%f, %f, %f", acc.x, acc.y, acc.z);

实例1:
#import "ViewController.h"
#import <CoreMotion/CoreMotion.h> @interface ViewController ()
@property (nonatomic, strong) CMMotionManager *mgr;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; // 1.创建coreMotion管理者
self.mgr = [[CMMotionManager alloc] init]; if (self.mgr.isAccelerometerAvailable) {
// 3.开始采样
[self.mgr startAccelerometerUpdates]; // pull
}else
{
NSLog(@"加速计不可用");
} } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CMAcceleration acceleration = self.mgr.accelerometerData.acceleration; NSLog(@"x = %f y = %f z = %f", acceleration.x, acceleration.y , acceleration.z);
} - (void)push
{
// 1.创建coreMotion管理者
// CMMotionManager *mgr = [[CMMotionManager alloc] init];
self.mgr = [[CMMotionManager alloc] init]; // 2.判断加速计是否可用
if (self.mgr.isAccelerometerAvailable) {
/*
isAccelerometerActive 是否正在采集
accelerometerData 采集到得数据
startAccelerometerUpdates pull
startAccelerometerUpdatesToQueue push
stopAccelerometerUpdates 停止采集
accelerometerUpdateInterval 采样时间
*/
// 3.设置采样时间
self.mgr.accelerometerUpdateInterval = / 30.0;
// 4.开始采样 [self.mgr startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
// 这个block是采集到数据时就会调用
if (error) return ;
CMAcceleration acceleration = accelerometerData.acceleration;
NSLog(@"x = %f y = %f z = %f", acceleration.x, acceleration.y , acceleration.z);
}];
}else
{
NSLog(@"加速计不可用");
}
} @end

实例2:

#import "HMViewController.h"
#import <CoreMotion/CoreMotion.h> @interface HMViewController ()
@property (nonatomic, strong) CMMotionManager *mgr;
@end @implementation HMViewController - (void)viewDidLoad
{
[super viewDidLoad]; // 1.创建motion管理者
self.mgr = [[CMMotionManager alloc] init]; // 2.判断加速计是否可用
if (self.mgr.isAccelerometerAvailable) {
[self pull];
} else {
NSLog(@"---加速计不可用-----");
}
}
/**
* ******* pull *******
*/
- (void)pull
{
[self.mgr startAccelerometerUpdates];
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CMAcceleration acceleration = self.mgr.accelerometerData.acceleration;
NSLog(@"%f %f %f", acceleration.x, acceleration.y, acceleration.z);
} /**
* ******* push *******
*/
- (void)push
{
// 3.设置采样间隔
self.mgr.accelerometerUpdateInterval = / 30.0; // 4.开始采样(采集加速度数据)
[self.mgr startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
// 如果在block中执行较好时的操作,queue最好不是主队列
// 如果在block中要刷新UI界面,queue最好是主队列
NSLog(@"%f %f %f", accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z);
}];
} @end

实例3:

#import "CZMotionManager.h"

/**
1. 静态的全局实例
2. allocWithZone
3. 定义一个shared方法,供全局使用
*/ // 保存当前类的实例
static CZMotionManager *_instance; @implementation CZMotionManager + (instancetype)shareMotionManager
{
if (_instance == nil) {
_instance = [[[self class] alloc] init];
}
return _instance;
} #pragma mark - 以下方法是为了保证对象在任何情况下都唯一
// 调用alloc的时候会调用这个方法
+ (id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
// 保证我们的block只能执行一次
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//会在调用copy的时候调用这个方法
- (id)copyWithZone:(NSZone *)zone
{
return self;
} //在调用mutableCopy的时候调用这个方法
- (id)mutableCopyWithZone:(NSZone *)zone
{
return self;
} @end
/*
>PPT讲解CoreMontion
*新建工程导入CoreMontion框架, 拷贝常规使用添加小球代码
*导入CoreMontion框架主头文件, 查看头文件讲解相关属性含义
*实例化运动管理器,—>判断加速计是否可用—>设置采样数据的时间间隔—>开始采样数据 —>更改小球位置
*从运行没有反应引出CoreMontionManage是局部变量
*新建队列替换主队列, 从运行程序没有任何反应引出修改更新方法在主队列中修改UI
*从系统提供的CoreMontionManage不是单例,引出定义子类实现单例(讲解如何实现单例)
*画图讲解从采样时间和刷帧时间不一样小球现实会不清晰引出采样和刷帧单独进行
*从加速计常用于游戏引出实现点击频幕后暂停游戏, 注意不需要每次都销毁CADisplayLink
*/ #import "CZViewController.h"
#import <CoreMotion/CoreMotion.h>
#import "CZMotionManager.h" @interface CZViewController ()
/**
* 小球
*/
@property (nonatomic, weak)UIImageView *ballIv;
/**
* 保存x y方向加速度
*/
@property (nonatomic, assign)CGPoint ballVelocity; /**
* 运动管理器
*/
@property (nonatomic, strong)CMMotionManager *motionM; @property (nonatomic, strong)NSOperationQueue *queue; @property (nonatomic, strong)CADisplayLink *link; @end @implementation CZViewController /**
运动管理器的属性 1> accelerometerUpdateInterval 加速计更新间隔
2> isAccelerometerAvailable 是否可用
3> accelerometerActive 是否正在采集数据
4> accelerometerData 加速计数据(通过Pull方式获得)
5> startAccelerometerUpdatesToQueue 开始加速计更新(通过Push方式实时获得采样数据)
6> stopAccelerometerUpdates 停止数据采样 */
- (void)viewDidLoad
{
[super viewDidLoad];
// 1.添加小球
UIImage *image = [UIImage imageNamed:@"black"];
UIImageView *iv = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:iv];
self.ballIv = iv; self.queue = [[NSOperationQueue alloc] init]; // 2.实例化运动管理器
// CMMotionManager *montionM = [[CMMotionManager alloc] init]; // self.motionM = [[CMMotionManager alloc] init];
self.motionM = [CZMotionManager shareMotionManager]; // 3.判断加速计是否可用
if (self.motionM.isAccelerometerAvailable) {
// 3.1设置采样时间间隔
self.motionM.accelerometerUpdateInterval = / 30.0;
/*
// 3.2 开始采样数据
// [self.motionM startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData * [self.motionM startAccelerometerUpdatesToQueue:self.queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { // NSLog(@"%@", [NSThread currentThread]); // 处理采样数据,修改小球速度
_ballVelocity.x += accelerometerData.acceleration.x;
_ballVelocity.y -= accelerometerData.acceleration.y; // 更改小球位置
// [self updateLocation];
}];
*/
// 3.2 开始采样数据
[self startAccelerometerUpdates];
}else
{
NSLog(@"摔坏了");
} // 4.实例化CADisplayLink
/*
在真机实际运行中,小球的显示并是不非常的清晰,会有一些发虚。
*/
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateLocation)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
self.link = link;
}
#pragma mark - 私有方法
#pragma mark 开始采样数据
- (void)startAccelerometerUpdates
{
// 3.2 开始采样数据
[self.motionM startAccelerometerUpdatesToQueue:self.queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
// 处理采样数据,修改小球速度
_ballVelocity.x += accelerometerData.acceleration.x;
_ballVelocity.y -= accelerometerData.acceleration.y; }];
} - (void)updateLocation
{
// 设置小球的位置
CGPoint center = self.ballIv.center;
CGSize size = self.view.bounds.size; // 解决小球出界问题,碰撞检测
// 水平方向:左边,右边
if (CGRectGetMinX(self.ballIv.frame) <= || CGRectGetMaxX(self.ballIv.frame) >= size.width) {
// 修改小球的速度方向
_ballVelocity.x *= -; // 修复位置 < 0
if (CGRectGetMinX(self.ballIv.frame) <= ) {
center.x = self.ballIv.bounds.size.width / 2.0;
} else {
center.x = size.width - self.ballIv.bounds.size.width / 2.0;
}
} // 垂直方向
if (CGRectGetMinY(self.ballIv.frame) <= || CGRectGetMaxY(self.ballIv.frame) >= size.height) {
// 修改小球的速度方向
_ballVelocity.y *= -; // 修复位置 < 0
if (CGRectGetMinY(self.ballIv.frame) <= ) {
center.y = self.ballIv.bounds.size.height / 2.0;
} else {
center.y = size.height - self.ballIv.bounds.size.height / 2.0;
}
} center.x += _ballVelocity.x;
center.y += _ballVelocity.y; // NSLog(@"%@", [NSThread currentThread]); // 在主线程队列上更新小球位置
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.ballIv.center = center;
}]; } // 游戏“暂停”——用户点击屏幕,暂停小球运动
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ if (self.motionM.isAccelerometerActive) {
// 停止
[self.motionM stopAccelerometerUpdates]; /*
invalidate停止时钟
1> 将时钟从主运行循环中撤销
2> 将时钟销毁
[_gameTimer invalidate];
*/ // 直接从主运行循环中将游戏时钟删除,而不会销毁时钟,等到需要时再次添加即可。
[self.link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}else
{
// 开始采样数据
[self startAccelerometerUpdates]; // 开启时钟
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
}
@end

IOS Core Motion、UIAccelerometer(加速计使用)的更多相关文章

  1. IOS 特定于设备的开发:Core Motion基础

    Core Motion框架集中了运动数据处理.该框架是在IOS 4 SDK中引入的,用于取代accelerometer加速计访问.它提供了对3个关键的机载传感器的集中式监测.这些传感器有陀螺仪.磁力计 ...

  2. iOS开发 传感器(加速计、摇一摇、计步器)

    一.传感器 1.什么是传感器传感器是一种感应\检测周围环境的一种装置, 目前已经广泛应用于智能手机上 传感器的作用用于感应\检测设备周边的信息不同类型的传感器, 检测的信息也不一样 iPhone中的下 ...

  3. iOS开发-CoreMotion框架(加速计和陀螺仪)

    CoreMotion是一个专门处理Motion的框架,其中包含了两个部分加速度计和陀螺仪,在iOS4之前加速度计是由UIAccelerometer类来负责采集数据,现在一般都是用CoreMotion来 ...

  4. 转 iOS Core Animation 动画 入门学习(一)基础

    iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Coco ...

  5. iOS - Core Animation 核心动画

    1.UIView 动画 具体讲解见 iOS - UIView 动画 2.UIImageView 动画 具体讲解见 iOS - UIImageView 动画 3.CADisplayLink 定时器 具体 ...

  6. IOS Core Image之二

    在上篇博客IOS Core Image之一中了解了下CIImage.CIFilter.CIContext三个类的使用,这篇了解下滤镜链(多滤镜)和人脸检测(不是人脸识别). 一.多滤镜 1.有些效果不 ...

  7. iOS Core ML与Vision初识

    代码地址如下:http://www.demodashi.com/demo/11715.html 教之道 贵以专 昔孟母 择邻处 子不学 断机杼 随着苹果新品iPhone x的发布,正式版iOS 11也 ...

  8. iOS Core Animation 简明系列教程

    iOS Core Animation 简明系列教程  看到无数的CA教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽 ...

  9. IOS Core Animation Advanced Techniques的学习笔记(一)

    转载. Book Description Publication Date: August 12, 2013 Core Animation is the technology underlying A ...

随机推荐

  1. Git merge rebase cherry-pick 以及 游离commit 的测试

    Microsoft Windows [版本 10.0.17134.345] (c) Microsoft Corporation.保留所有权利. C:\Users\zhangyang\Desktop\b ...

  2. 在Linux系统中,使用useradd命令新建用户后,登录该用户时shell开头为$,不显示用户名和路径,如下:

    在~/.bash_profile中加入以下代码,若无该文件可自行创建: vi ~/.bash_profile #加入 #export PS1='[u@h W]$' 大写W代表最后路径,小写w代表详细路 ...

  3. 让android系统中任意一个view变成进度条

    1.效果 2.进度条背景drawable文件 结束后可以恢复原背景. <?xml version="1.0" encoding="utf-8"?> ...

  4. vm12下Centos6的javaweb环境搭建

    配置linux的javaweb环境之前: 1.在windows安装xshell(非必需,但是推荐) 2.在linux安装Linux与windows文件传输工具RZSZ[root@192 ~]# yum ...

  5. webstorm 搜索vue文件

    1. Show IDE settings 状态修改为 ON

  6. 使用windows的BitLocker+VHD加密“文件夹”

    进入磁盘管理 创建VHD,选定位置 初始化创建的虚拟盘,新建简单卷 给新的盘启用BitLocker 其他: 快速锁定:manage-bde.exe D: -lock  -fd

  7. linux_api之进程环境(二)

      本篇索引: 1.引言 2.终端登录 3.进程组 4.会话期 1.引言 通过上一篇的学习,我们已经知道了如何控制一个进程,fork函数从父进程中复制出子进程,我们可以通过exec函数让子进程运行新的 ...

  8. NetCDF 共享软件 中文

    NetCDF 共享软件   转载 在 Models-3 模式中,使用的数据存取接口称为 I/O API,其实就是 NetCDF 文件格式.而由于我们需要了解 Models-3 输出档案的数据情况,因此 ...

  9. 《Python编程从入门到实践》_第七章_用户输入和whlie循环

    函数input()的工作原理 函数input()让程序暂停运行,等待用户输入一些文本.获取用户输入后,python将其存储在一个变量中,以方便你使用. #输入用户名 username = input( ...

  10. 浏览器后退->清除原页面div中填写的数据

    需求说明:页面表单用前端用div布局,提交之后跳转到另一个页面,但是考虑到客户奇怪的脑回路,可能会点击浏览器的后退按钮,不知道是个体情况还是都是一样,原本div中填写的数据还依然存在,所以需要让页面在 ...