iOS零碎知识iOS学习资料整理+学习方法斯坦福大学iOS课程

斯坦福大学iOS开发公开课总结(十七) :Core Motion

2016-08-06  本文已影响714人  J_Knight_

本节课讲解了Core Motion框架的知识,简单介绍了app的生命周期,最后用一个方块碰撞游戏来对本节课的知识作总结。

Core Motion


CoreMotion是一个专门处理设备“动作”的框架,其中包含了加速度计,陀螺仪和磁力针。加速计由三个坐标轴决定,用户最常见的操作设备的动作移动,晃动手机(摇一摇),倾斜手机都可以被设备检测到,加速计可以检测到线性的变化。陀螺仪可以更好的检测到偏转的动作,可以根据用户的动作做出相应的动作;磁力针可以判断设备的方向。

CoreMotion的工作是基于CMMotionManager类来执行的。我们看一下该类的API:

CMMotionManager

检测硬件设备:

@property(readonly, nonatomic, getter=isAccelerometerAvailable) BOOL accelerometerAvailable __TVOS_PROHIBITED;
@property(readonly, nonatomic, getter=isGyroAvailable) BOOL gyroAvailable __TVOS_PROHIBITED;
@property(readonly, nonatomic, getter=isMagnetometerAvailable) BOOL magnetometerAvailable NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
@property(readonly, nonatomic, getter=isDeviceMotionAvailable) BOOL deviceMotionAvailable __TVOS_PROHIBITED;

开启相应的模块:

- (void)startAccelerometerUpdates __TVOS_PROHIBITED;
- (void)startGyroUpdates __TVOS_PROHIBITED;
- (void)startMagnetometerUpdates NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
- (void)startDeviceMotionUpdates __TVOS_PROHIBITED;

检测相应的模块是否正在收集数据:

@property(readonly, nonatomic, getter=isAccelerometerActive) BOOL accelerometerActive __TVOS_PROHIBITED;
@property(readonly, nonatomic, getter=isGyroActive) BOOL gyroActive __TVOS_PROHIBITED;
@property(readonly, nonatomic, getter=isMagnetometerActive) BOOL magnetometerActive NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
@property(readonly, nonatomic, getter=isDeviceMotionActive) BOOL deviceMotionActive __TVOS_PROHIBITED;
    

关闭相应的模块:


- (void)stopAccelerometerUpdates __TVOS_PROHIBITED;

- (void)stopGyroUpdates __TVOS_PROHIBITED;

- (void)stopMagnetometerUpdates NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
- (void)stopDeviceMotionUpdates __TVOS_PROHIBITED; 

使用block监听

- (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler __TVOS_PROHIBITED;
- (void)startGyroUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMGyroHandler)handler __TVOS_PROHIBITED;

- (void)startMagnetometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMMagnetometerHandler)handler NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;
- (void)startDeviceMotionUpdatesUsingReferenceFrame:(CMAttitudeReferenceFrame)referenceFrame toQueue:(NSOperationQueue *)queue withHandler:(CMDeviceMotionHandler)handler NS_AVAILABLE(NA,5_0) __TVOS_PROHIBITED;

CMMotionManager的工作步骤

  1. 首先初始化CMMotionManager类。
  2. 判断硬件设备的可使用性。
  3. 调用API
    详细的使用方法请看Demo部分的讲解部分。

app的生命周期


程序在运行过程中,是由各种不同的状态的,在这些状态之间切换时可以执行一些代码用于满足一定的业务需求。

应用程序的几种状态:

应用程序的状态之间切换时调用的代理方法(AppDelegate):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   //启动基本完成,程序准备开始运行时调用。
- (void)applicationWillResignActive:(UIApplication *)application          //当应用程序将要入非活动状态执行。在此期间,应用程序不接收消息或事件,比如来电话时。
- (void)applicationDidBecomeActive:(UIApplication *)application           //当应用程序入活动状态执行。
- (void)applicationDidEnterBackground:(UIApplication *)application        //当程序被推到后台的时候调用。
- (void)applicationWillEnterForeground:(UIApplication *)application       //当程序从后台将要重新回到前台时候调用。
- (void)applicationWillTerminate:(UIApplication *)application             // 当程序将要退出时调用,通常是用来保存数据和一些退出前的清理工作。

Demo


Demo需求:

Demo效果图:

左:游戏进行中 | 右:游戏暂停

重要知识点和代码段:

1. 添加animator和重力行为和碰撞行为

- (UIDynamicAnimator *)animator
{
    if (!_animator) _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    return _animator;
}

- (UICollisionBehavior *)collider
{
    if (!_collider) {
        UICollisionBehavior *collider = [[UICollisionBehavior alloc] init];
        collider.translatesReferenceBoundsIntoBoundary = YES;
        [self.animator addBehavior:collider];
        self.collider = collider;
    }
    return _collider;
}

- (UIGravityBehavior *)gravity
{
    if (!_gravity) {
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init];
        [self.animator addBehavior:gravity];
        self.gravity = gravity;
    }
    return _gravity;
}

老规矩,还是要将animtor添加到view里面再向其添加各种动作行为。有关动画的讲解请参考笔者之前一篇总结:斯坦福大学iOS开发公开课总结(八) :协议,block,动画,俄罗斯方块Demo

2. 根据偏移量来设置方块的位置

- (UIView *)addBlockOffsetFromCenterBy:(UIOffset)offset
{
    CGPoint blockCenter = CGPointMake(CGRectGetMidX(self.view.bounds)+offset.horizontal,
                                      CGRectGetMidY(self.view.bounds)+offset.vertical);

    CGRect blockFrame = CGRectMake(blockCenter.x-blockSize.width/2,
                                   blockCenter.y-blockSize.height/2,
                                   blockSize.width,
                                   blockSize.height);

    UIView *block = [[UIView alloc] initWithFrame:blockFrame];
    [self.view addSubview:block];
    return block;
}

在这里,使用了CGRectGetMidX函数来获得view的横向中心点。

3. 初始化红色和黑色方块

        self.redBlock = [self addBlockOffsetFromCenterBy:UIOffsetMake(-100, 0)];
        self.redBlock.backgroundColor = [UIColor redColor];
        [self.collider addItem:self.redBlock];
        [self.gravity addItem:self.redBlock];
        
        self.blackBlock = [self addBlockOffsetFromCenterBy:UIOffsetMake(+100, 0)];
        self.blackBlock.backgroundColor = [UIColor blackColor];
        [self.collider addItem:self.blackBlock];

        //将开始的重力设为0:方块将不感受重力,只能通过人为手段施加
        self.gravity.gravityDirection = CGVectorMake(0, 0);

在这里,红色方块具有碰撞和重力行为,但是黑色方块却只有碰撞行为。因为黑色是不受重力控制的,它的运动的触发只来自红色方块的碰撞。

4. 在程序即将要挂起或者恢复前台活动状态时进行暂停游戏的操作:

    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification
                                                      object:nil
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
                                                      [self pauseGame];
                                                  }];

    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification
                                                     object:nil
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
                                                      if (self.view.window) [self resumeGame];
                                                  }];

我们也可以在appdelegate里面来实现这些方法,不过个人认为将方法写在一起看起来比较直观

5. CMMotionManager的初始化和使用

//初始化
- (CMMotionManager *)motionManager
{
    if (!_motionManager) {
        _motionManager = [[CMMotionManager alloc] init];
        _motionManager.accelerometerUpdateInterval = 0.1;
    }
    return _motionManager;
}

//将方法放在主线程的代码块中
 if (!self.motionManager.isAccelerometerActive) {

        [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]

                                                 withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
                                                    //获取加速器的方向
                                                     CGFloat x = accelerometerData.acceleration.x;
                                                     CGFloat y = accelerometerData.acceleration.y;
                                    
                                                    //根据设备的方向来给方块施加不同方向的重力
                                                     switch (self.interfaceOrientation) {
                                                         case UIInterfaceOrientationLandscapeRight:
                                                            self.gravity.gravityDirection = CGVectorMake(- y, - x); break;
  
                                                       case UIInterfaceOrientationLandscapeLeft:
                                                             self.gravity.gravityDirection = CGVectorMake(y, x); break;

                                                         case UIInterfaceOrientationPortrait:
                                                             self.gravity.gravityDirection = CGVectorMake(x, - y); break;

                                                         case UIInterfaceOrientationPortraitUpsideDown:
                                                            self.gravity.gravityDirection = CGVectorMake(- x, y); break;
                                                     }

                                                     [self updateScore];
                                                 }];
    }
```

#最后的话
----
如果哪位小伙伴想拿到本文Demo的代码请不要客气,可以进入我的[GitHub](https://github.com/Shijie0111/Stanford_iOS_Lecture_DemoBundle)下载哦~    这一系列到现在为止的所有Demo都在里面,分为英文注释版本和中文注释版本两种。

如果嫌麻烦的童鞋可以在留言留下邮箱,笔者会将Demo包发给你~

十分欢迎给笔者的代码和文笔抛出宝贵的意见和建议~

本文已在版权印备案,如需转载请访问版权印。48422928

[获取授权](http://101702070004705.bqy.pub)
上一篇 下一篇

猜你喜欢

热点阅读