开发者社区> 异步社区> 正文

《iOS 6高级开发手册(第4版)》——1.10节秘诀:Core Motion基础

简介:
+关注继续查看

本节书摘来自异步社区《iOS 6高级开发手册(第4版)》一书中的第1章,第1.10节秘诀:Core Motion基础,作者 【美】Erica Sadun,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.10 秘诀:Core Motion基础
iOS 6高级开发手册(第4版)
Core Motion框架集中了运动数据处理。该框架是在iOS 4 SDK中引入的,用于取代你刚才阅读到的直接加速计访问。它提供了对3个关键的机载传感器的集中式监测。这些传感器由陀螺仪、磁力计和加速计组成,其中陀螺仪用于测量设备的旋转,磁力计提供了一种测量罗盘方位的方式,加速计用于检测沿着3根轴的重力变化。第四个入口点称为设备移动(device motion),它把全部3种传感器都结合进单个监测系统中。

Core Motion使用来自这些传感器原始值创建可度的测量结果,主要表现为力向量的形式。可测量的项包括以下属性。

设备姿势(attitude):设备相对于某个参照画面的方向。姿势被表示为摇晃、前倾和左右摇摆的角度,它们都以弧度为单位。
旋转速率(rotationRate):设备围绕它的3根轴中的每一根轴旋转的速率。旋转包括x、y和z角速度值,它们以弧度/秒为单位。
重力(gravity):设备当前的加速度向量,由正常的重力场提供。重力的单位是g's,分别沿着x、y和z轴来测量。每个单位代表由地球提供的标准重力加速度(9.8米/秒2)。
用户加速度(userAcceleration):用户提供的加速度向量。像重力一样,用户加速度的单位也是g's,分别沿着x、y和z轴来测量。当把它们加到一起时,用户向量和重力向量代表给设备提供的总加速度。
磁场(magneticField):代表设备邻近区域里的总磁场的向量。磁场是沿着x、y和z轴以微特斯拉(microtesla)为单位测量的。还提供了校准精度,通知应用程序有关磁场测量的质量。

1.10.1 测试传感器
正如在本章前面所学到的,可以使用应用程序的Info.plist文件要求使用或排除机载传感器。也可以在应用程序内测试每种可能的Core Motion支持:

if (motionManager.gyroAvailable)
    [motionManager startGyroUpdates];

if (motionManager.magnetometerAvailable)
    [motionManager startMagnetometerUpdates];

if (motionManager.accelerometerAvailable)
    [motionManager startAccelerometerUpdates];

if (motionManager.deviceMotionAvailable)
    [motionManager startDeviceMotionUpdates];

开始更新不会产生像使用UIAccelerometer时遇到的委托回调机制。作为替代,你将负责轮询每个值,或者可以使用基于块的更新机制,执行在每次更新时提供的一个块(例如,startAccelerometerUpdatesToQueue:withHandler:)。

1.10.2 处理程序块
秘诀1-6修改了秘诀1-4,以便使用Core Motion。把加速度回调移入一个处理程序块中,并从数据的加速度属性中读取x和y值。否则,代码将保持不变。在这里,将看到Core Motion的一些基本的方面:创建一个新的运动管理器,它用于测试加速计可用性。然后,它将使用一个新的操作队列开始更新,该队列在应用程序运行期间将持续存在。

establishMotionManager和shutDownMotionManager方法使应用程序能够根据需要启动和关闭运动管理器。这些方法是在应用程序变成活动时和挂起时从应用程序委托内调用的:

- (void) applicationWillResignActive:(UIApplication *)application
{
    [tbvc shutDownMotionManager];
}

- (void) applicationDidBecomeActive:(UIApplication *)application
{
    [tbvc establishMotionManager];
}

这些方法提供了一种干净的方式,用于关闭和恢复运动服务,以响应当前的应用程序状态。

秘诀1-6 基本的Core Motion

@implementation TestBedViewController
- (void) tick
{
    butterfly.transform = CGAffineTransformIdentity;

    // Move the butterfly according to the current velocity vector
    CGRect rect = CGRectOffset(butterfly.frame, xvelocity, 0.0f);
    if (CGRectContainsRect(self.view.bounds, rect))
        butterfly.frame = rect;

    rect = CGRectOffset(butterfly.frame, 0.0f, yvelocity);
    if (CGRectContainsRect(self.view.bounds, rect))
        butterfly.frame = rect;

        butterfly.transform =
            CGAffineTransformMakeRotation(mostRecentAngle + M_PI_2);
}
- (void) shutDownMotionManager
{
    NSLog(@"Shutting down motion manager");
    [motionManager stopAccelerometerUpdates];
    motionManager = nil;
    [timer invalidate];
    timer = nil;
}

- (void) establishMotionManager
{
    if (motionManager)
        [self shutDownMotionManager];

    NSLog(@"Establishing motion manager");

    // Establish the motion manager
    motionManager = [[CMMotionManager alloc] init];
    if (motionManager.accelerometerAvailable)
        [motionManager
            startAccelerometerUpdatesToQueue:
                [[NSOperationQueue alloc] init]
        withHandler:^(CMAccelerometerData *data, NSError *error)
        {
            // Extract the acceleration components
            float xx = -data.acceleration.x;
            float yy = data.acceleration.y;
            mostRecentAngle = atan2(yy, xx);

            // Has the direction changed?
            float accelDirX = SIGN(xvelocity) * -1.0f;
            float newDirX = SIGN(xx);
            float accelDirY = SIGN(yvelocity) * -1.0f;
            float newDirY = SIGN(yy);

            // Accelerate. To increase viscosity,
            // lower the additive value
            if (accelDirX == newDirX)
                xaccel = (abs(xaccel) + 0.85f) * SIGN(xaccel);
            if (accelDirY == newDirY)
                yaccel = (abs(yaccel) + 0.85f) * SIGN(yaccel);
            // Apply acceleration changes to the current velocity
            xvelocity = -xaccel * xx;
            yvelocity = -yaccel * yy;
        }];

    // Start the physics timer
    timer = [NSTimer scheduledTimerWithTimeInterval: 0.03f
    target: self selector: @selector(tick)
    userInfo: nil repeats: YES];
}

- (void) initButterfly
{
    CGSize size;

    // Load the animation cells
    NSMutableArray *butterflies = [NSMutableArray array];
    for (int i = 1; i <= 17; i++)
    {
        NSString *fileName =
            [NSString stringWithFormat:@"bf_%d.png", i];
        UIImage *image = [UIImage imageNamed:fileName];
        size = image.size;
        [butterflies addObject:image];
    }

    // Begin the animation
    butterfly = [[UIImageView alloc]
        initWithFrame:(CGRect){.size=size}];
    [butterfly setAnimationImages:butterflies];
    butterfly.animationDuration = 0.75f;
    [butterfly startAnimating];

    // Set the butterfly's initial speed and acceleration
    xaccel = 2.0f;
    yaccel = 2.0f;
    xvelocity = 0.0f;
    yvelocity = 0.0f;

    // Add the butterfly
    butterfly.center = RECTCENTER(self.view.bounds);
    [self.view addSubview:butterfly];
    }

- (void) loadView
{
    [super loadView];
    self.view.backgroundColor = [UIColor whiteColor];
    [self initButterfly];
}
@end

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Core Image:iOS图像处理技术追踪
Core Image是苹果官方提供的图像处理框架,通过丰富的built-in(内置)或自定义Filter(过滤器)高效处理静态图片、动态图片或视频。开发者还可以通过构造Filter链或自定义Core Image Kernel来实现更丰富的效果。 在WWDC20中,苹果官方针对Core Image技术在以下三方面做了优化:Core Image对视频/动图的支持、基于Metal构建Core Image (CI) Kernel以及Core Image的Debug支持。 这三方面会在下文逐一提到,文末笔者也会浅谈Core Image在手淘图片库中的应用可能以及对Core Image技术的展望。
1641 0
iOS 开源图形库 Core Plot 使用教程
本文讲的是iOS 开源图形库 Core Plot 使用教程,但是如果你不想花费时间和精力从零开始写(代码),也不想花那么多钱,该怎么办呢?这时候第三个选项就派上用场了:使用开源库 Core Plot!
1257 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
文章
问答
视频
相关电子书
更多
深入剖析iOS性能优化
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载