传感器技术

传感器技术

加速计传感器(微信摇一摇,计步器)

目标: 演示加速剂的使用,做一个小球滚动的游戏.
关键词:Accelerrmoter
作用:检测设备在x,y,z的加速度(力的作用)

  1. 导入框架CoreMotion.

  2. 核心类:CMMotionmanager.动作管理者,包含加速度数据,加速度数据和磁场数据等.

  3. 逻辑代码部分
    3.0. 判断硬件是否支持
    3.1. 获取加速度数据.
    3.2. 提供了两种获取方式
    1.push(推送)实时向你推送.使用队列,通过block定时执行.
    1. 判断是否是激活加速计状态.??pull需要么??
    2.pull(拉取)在你需要数据的时候,主动获取.开启速度更新
    2. 通过acceleremoterData属性,去获取数据.
    小球是通过push.因为要实时更新.
    ============== 让小球滚起来. ===========
    利用x,y的值,来给小球添加作用力(将0.5的力放大),竖直偏移是它向下移动,水平偏移是它左右移动.

  4. 注意点生命周期问题:图层.改圆角,不能再viewDidload中改,也不能在viewWillAppear(还没布局),在ViewDidAppear也不行,会跳动先方后圆.最后知道了ViewDidLayoutSubviews中写.这个时候自动布局才已经改变了.

// 用于接收和处理`加速事件`和其它的动作事件
#import 

- (void)viewDidLoad {
    [super viewDidLoad];
  
    // ========== 1. 获取加速度的数据 ==========
    
    // 1. 判断加速计是否可用
    if (self.motionManager.accelerometerAvailable == NO) {
        NSLog(@"不支持该硬件!");
        return;
    }
    
    // ========== 2. 获取数据 (Pull方式) ==========
    
    // 1.0 秒更新一次数据
    self.motionManager.accelerometerUpdateInterval = 1.0;
    
    // 1. 激活加速计 (提供数据)
    // 开始更新新数据 (Pull方式)
    [self.motionManager startAccelerometerUpdates];
    
    // [self.motionManager stopAccelerometerUpdates];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // ========== 在点击时, 获取加速计的数据 ==========
    // 通过一个属性来获取到最新的加速计数据
    CMAccelerometerData *data = self.motionManager.accelerometerData;
    
    // 加速计数据
    CMAcceleration acce = data.acceleration;
    
    NSLog(@"%f, %f, %f", acce.x, acce.y, acce.z);
}

#pragma mark - Getter & Setter

- (CMMotionManager *)motionManager
{
    if (_motionManager == nil) {
        _motionManager = [[CMMotionManager alloc] init];
    }
    return _motionManager;
}

#pragma mark - 小球案例
/*
 在self.view 的 layoutSubviews 执行完成
 当该方法执行时, 子视图已经布局完成
 * 当view的frame值或者它的子视图的frame被修改, 需要重新布局
 */
- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    
    self.imageView.layer.cornerRadius = self.imageView.bounds.size.width * 0.5;
    // IB中也可以设置 clipToBounds
    // self.imageView.clipsToBounds = YES;
    // self.imageView.layer.masksToBounds = YES;
}

  // 开始更新加速计数据 (Push, 定时更新)
        [self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
            if (error) {
                NSLog(@"获取数据失败! %@", error);
                return;
            }
            // CMAccelerometerData : 表示加速计的数据
            // CMAcceleration : 表示加速度的结构体
            CMAcceleration data = accelerometerData.acceleration;
            NSLog(@"%f, %f", data.x, data.y);
            
            // ========== 让小球滚动 ==========
            // 1. 利用x, y的值, 来给小球添加作用力 (将0.5的力放大成10像素)
            CGFloat speedX = data.x * 30;
            CGFloat speedY = data.y * 30;
            // NSLog(@"%f, %f", speedX, speedY);
            
            // 2. 改变frame值, 让小球滚动
            CGRect rect = self.imageView.frame;
            rect.origin.x += speedX;
            // y方向的数据要颠倒
            rect.origin.y += -speedY;
            
            [UIView animateWithDuration:0.25 animations:^{
                self.imageView.frame = rect;
            }];
            
            NSLog(@"%@", NSStringFromCGRect(self.imageView.frame));
            
            // 在非主线程当中更新UI界面, frame值会改变, 但是界面是没有影响(不确定)
        }];

陀螺仪(赛车类游戏)
目标:掌握陀螺仪的使用
* 获取角速度

关键类:CMMotionManager,关键字:Groy

  1. 同加速度前面部分代码.
  2. push获取数据
    2.1. 判断是否激活,激活
    2.2. 开始陀螺仪数据更新
    2.3. 获取旋转速率(角速度),x,y,z这里面代表三个方向旋转的角速度数据.
  3. pull方式(类比上面)
代码部分都类似距离传感器
[self.motionManager startGyroUpdates];

[self.motionManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMGyroData * _Nullable gyroData, NSError * _Nullable error) {
            
            // CMGyroData : 表示陀螺仪的数据
            // CMRotationRate : 表示旋转速率, 角速度的结构体,
            CMRotationRate rate = gyroData.rotationRate;
            
            // 静止状态下, 值是接近于0的
            NSLog(@"%f, %f, %f", rate.x, rate.y, rate.z);
        }];

计步器来统计数据

关键类:
CMStepCounter早期使用的,
CMPedometer取代前面的检测走了多少步.
类似上面,也是通过计步数据对象,的各个属性获取相关值.

#import 

// 1. 实例化一个计步器
    self.pedometer = [[CMPedometer alloc] init];
    
    // 开始统计相关的行走信息 (开始统计的时间)
    // 会定时的触发Block方法, 没办法设置
    [self.pedometer startPedometerUpdatesFromDate:[NSDate date] withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
        
        // CMPedometerData: 表示计步器所统计的数据
        
        // ========== 检测走了多少步 ==========
        // 1. 判断该检测是否可用 (依赖硬件)
        if ([CMPedometer isStepCountingAvailable] == NO) {
            NSLog(@"不支持步数的计算统计");
            return;
        } else {
            // 走了几步
            NSNumber *number = pedometerData.numberOfSteps;
            NSLog(@"走了%zd步", number.intValue);
        }
        
        // ========== 检测走了多少米 ==========
        if ([CMPedometer isDistanceAvailable] == YES) {
            NSNumber *distance = pedometerData.distance;
            NSLog(@"走了%f米", distance.floatValue);
        }
    }];
距离传感器(靠近手机,打电话)

相关框架:CoreMotion(动作)
观察相关类,没有发现距离传感器的类(特别没有专门的类),是通过UIDevice来获取的.
关键字proximity距离.
UIDevice可以用来判断系统版本.

  1. [UIDevice currentDevice].proximityMonitoring默认关闭的
  2. 不是所有的设备都有距离传感器的.判断方法特别.
    Demo目标:类似微信的语音播放,扬声器和听筒切换
    思路:
  3. 距离传感器判断是否靠近屏幕.
  4. 根据状态,修改声音的输出.

知识点: UIDevice类内,有距离传感器状态改变的通知
代码:

  1. 开启距离传感器
  2. 添加接收系统通知
  3. 播放声音改变,关键类:AVAudioSession(音频会话),是个单例,有个重写输出音频端口的方法.
  4. 猜想根据通知参数的userInfo,获取当前的距离传感器状态,但是打印发现没有数据,只是通知你改变了状态了.
  5. 观看文档发现直接通过获取设备的proximityState属性,来判断是否靠近设备.

前提是需要向系统声明我所需要使用的音频相关功能.只需要走一次

  1. AVAudioSession单例有个setCategory方法进行类别的设置,参数是你需要做的功能.
  2. 修改声音的输出端口,是听筒还是扬声器.
  3. 播放音乐AVAudioPlayer 播放音乐的类,1.实例化,2.调用播放方法.
代码部分
导入
#import 

  // ========== 1. 开启距离传感器 ==========
    if ([[UIDevice currentDevice] isProximityMonitoringEnabled] == NO) {
        NSLog(@"当前距离传感器没有打开");
        
        // 尝试打开距离传感器, 如果失败了, 意味着不支持该硬件
        [[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
        
        // 打开结果判断 (是否支持硬件)
        if ([[UIDevice currentDevice] isProximityMonitoringEnabled] == NO) {
            NSLog(@"不支持该硬件, 无法使用");
        } else {
            NSLog(@"成功打开距离传感器");
            
            // ========== 2. 监听通知 ==========
            // 监听通知
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityDidChangeAction:) name:UIDeviceProximityStateDidChangeNotification object:nil];
        }
    }
    
    // ========== 2. 向系统声明, 所使用的音频的相关功能 ==========
    // 告诉系统, 本应用会使用哪一些与音频相关的功能
    NSError *error;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord  error:&error];
    if (error) {
        NSLog(@"音频功能声音出错: %@", error);
    }
    
    // ========== 3. 测试: 播放歌曲 ==========
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"南征北战 - 我的天坑.mp3" withExtension:nil];
    // 实例化音乐播放器
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    if (error) {
        NSLog(@"歌曲播放出错");
    }
    // 开始播放
    [self.player play];

- (void)proximityDidChangeAction:(NSNotification *)notification
{
    // ========== 1. 判断是否靠近屏幕 ==========
    // 并没有通过userInfo来携带数据, 应该直接获取距离传感器的proximityState属性
    NSLog(@"%@", notification.userInfo);
    
    /** 音频会话
     1. 设置应用当前所处的音频环境 (播放声音, 录音, 用什么来播放)
     2. 向系统诠释应用使用音频相关行为的意图
     */
    
    // 设置音频的输出设备 (听筒或扬声器)
    /**
     AVAudioSessionPortOverrideNone    = 0,  (扬声器)
     AVAudioSessionPortOverrideSpeaker  (听筒)
     */
    AVAudioSessionPortOverride port = [UIDevice currentDevice].proximityState == NO ? AVAudioSessionPortOverrideSpeaker : AVAudioSessionPortOverrideNone;

    NSError *error;
    [[AVAudioSession sharedInstance] overrideOutputAudioPort:port error:&error];
    if (error) {
        NSLog(@"改变声音输出失败");
    }
}

- (void)dealloc
{
    // 移除观察者
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
磁力传感器(了解,不常使用)
温度传感器(系统自动做的)
湿度传感器(保修用的)

你可能感兴趣的:(传感器技术)