模拟CoreMotion iOS模拟器

亚当

我正在尝试开发利用CoreMotion框架的应用程序。我不想一直用尽来测试我的应用程序,因此我想找到一种技术,该技术可以让我发送虚假的信息,以便可以尝试许多不同的场景。我希望测试用户步行,开车,停车等情况。我不想每次要测试应用程序时都必须走出去,开车,停车等。

编辑:我知道模拟器中尚不支持CoreMotion。但是希望有人可以给我一些假冒的想法

更新:到目前为止,我已经使用方法转换实现了什么。我已经换回了objective-c,因为我认为最好先尝试用这种语言,然后再尝试将其翻译成Swift。

我已经建立了这样的方法混淆类

+ (void)swizzleClass:(Class)class method:(NSString*)methodName {

  SEL originalSelector = NSSelectorFromString(methodName);
  SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"%@%@", @"override_", methodName]);

  Method originalMethod = class_getInstanceMethod(class, originalSelector);
  Method newMethod = class_getInstanceMethod(class, newSelector);

  method_exchangeImplementations(originalMethod, newMethod);
}

我为CMMotion和CMAccelerometerData创建了一个类别

- (void) simx_setAcceleration:(CMAcceleration)acceleration {
  NSValue *value = [NSValue value:&acceleration withObjCType:@encode(CMAcceleration)];
  objc_setAssociatedObject(self, ACCELERATION_IDENTIFIER, value, OBJC_ASSOCIATION_RETAIN);
}

- (CMAcceleration)override_acceleration {
  NSValue *value = objc_getAssociatedObject(self, ACCELERATION_IDENTIFIER);
  CMAcceleration acc;
  [value getValue:&acc];
  return acc;
}

然后是CMMotionManager类的类别。

- (void) simx_setAccelerationData:(CMAcceleration )accelerationData
{
    NSValue *value = [NSValue value:&accelerationData withObjCType:@encode(CMAcceleration)];
    objc_setAssociatedObject(self, HANDLER_IDENTIFIER, value, OBJC_ASSOCIATION_RETAIN);
}

- (CMAccelerometerData *)override_accelerometerData
{
    NSValue *value = objc_getAssociatedObject(self, HANDLER_IDENTIFIER);
    CMAcceleration acc;
    [value getValue:&acc];

    CMAccelerometerData *data = [[CMAccelerometerData alloc] init];

    //Add
    [data simx_setAcceleration:acc];

    return data;
}

麻烦的方法是这样完成的

 [CESwizzleUtils swizzleClass:[CMMotionManager class]
                              method:@"INSERT METHOD NAME TO BE SWIZZLED HERE"];

这使我可以传递自己的数据

 //Add
    CMAccelerometerData *data = [[CMAccelerometerData alloc] init];
    [data simx_setAcceleration:acc];
    [motionManager simx_setAccelerationData:acc];

所以我可以像这样检索数据

motionManager.accelerometerData.acceleration.x;

我也有方法使DeviceMotion类陷入困境。这是我提供的快速示例应用程序,它使用旋转技巧方法从加速度计和陀螺仪提取数据

在此处输入图片说明

单击测试按钮后,它将随机生成加速度计和陀螺仪数据并更新标签。

代码看起来像这样

-(IBAction)testing:(id)sender
{
  //random double just generates a random double between 0 and 1
    CMAcceleration acc;
    acc.x = [self randomDouble:0 :1];
    acc.y = [self randomDouble:0 :1];
    acc.z = [self randomDouble:0 :1];

    //Add
    CMAccelerometerData *data = [[CMAccelerometerData alloc] init];
    [data simx_setAcceleration:acc];
    [motionManager simx_setAccelerationData:acc];

    //Sim gravity and userAcel
    CMAcceleration grav;
    grav.x = [self randomDouble:0 :1];
    grav.y = [self randomDouble:0 :1];
    grav.z = [self randomDouble:0 :1];

    CMAcceleration userAcel;
    userAcel.x = [self randomDouble:0 :1];
    userAcel.y = [self randomDouble:0 :1];
    userAcel.z = [self randomDouble:0 :1];

    CMDeviceMotion *deviceMotion = [[CMDeviceMotion alloc] init];
    [deviceMotion simx_setUserAcceleration:userAcel];
    [deviceMotion simx_setGravity:grav];
    [motionManager simx_setDeviceMotion:deviceMotion];

    accelLabael.text = [NSString stringWithFormat:@"Accelerometer: %.02f %.02f %.02f", motionManager.accelerometerData.acceleration.x,motionManager.accelerometerData.acceleration.y,motionManager.accelerometerData.acceleration.z];

    gravityLabel.text = [NSString stringWithFormat:@"Gravity: %.02f %.02f %.02f", motionManager.deviceMotion.gravity.x,motionManager.deviceMotion.gravity.y,motionManager.deviceMotion.gravity.z];


    accelSpeedLabel.text = [NSString stringWithFormat:@"Accel: %.02f %.02f %.02f", motionManager.deviceMotion.userAcceleration.x,motionManager.deviceMotion.userAcceleration.y,motionManager.deviceMotion.userAcceleration.z];
}

我正在努力弄清楚如何获得这种方法。我已经花了很多CoreMotion方法,但是在此方面需要一些帮助。目前,在模拟器上,尽管MotionManager现在为陀螺仪,加速度计等存储数据,但这些块方法不会触发。

 [activityManager startActivityUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:   ^(CMMotionActivity *activity){

}];


 [motionManager startDeviceMotionUpdatesToQueue:[[NSOperationQueue alloc] init]
                                           withHandler:^ (CMDeviceMotion *motionData, NSError *error) {

}];

我也弄晕了这些方法

- (BOOL)override_isAccelerometerActive;
- (BOOL)override_isDeviceMotionActive;
-(BOOL)override_isGyroAvailable;

因此,它们始终返回true,但仍无法触发这些块。我希望获得一些帮助,以帮助您弄清楚如何正确处理这些方法,以便开始向模拟器发送和接收模拟数据

编辑:我确实通过添加以下类别来解决加速度计的更新方法。到CMMotionManager类

-(void)override_startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue
                                     withHandler:(CMAccelerometerHandler)handler{

    dispatch_async(dispatch_get_main_queue(), ^{

        NSLog(@"Test %.02f %.02f %.02f", self.accelerometerData.acceleration.x,self.accelerometerData.acceleration.y,self.accelerometerData.acceleration.z);


    });
}

由于我已经模糊了加速数据,因此效果很好。

然后,我通过添加此类别对CMMotionActivityManager类进行了尝试

-(void)override_startActivityUpdatesToQueue:(NSOperationQueue *)queue
                                withHandler:(CMMotionActivity *)activity
{
    dispatch_async(dispatch_get_main_queue(), ^
                   {
                      BOOL walking = [activity walking];
                       NSLog(@"%i", walking);
                   });
}

但是我在这里得到这个错误

[ NSGlobalBlock步行]:无法识别的选择器已发送到实例0x1086cf330

任何建议,将不胜感激

更新2:

抱歉,回复晚,只能等到今天才能尝试。我已根据您的建议更新了方法,因此现在可以使用

-(void)override_startActivityUpdatesToQueue:(NSOperationQueue *)queue
                                withHandler:(CMMotionActivityHandler )activity
{

}

事情是,我需要访问CMMotionActivity才能确定他们是否正在跑步等。原始代码

 [activityManager startActivityUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:   ^(CMMotionActivity *activity){
        dispatch_async(dispatch_get_main_queue(), ^
        {
            [activity walking];
        });
    }];

允许您访问此变量。但是,现在我已经解决了这个问题,它现在在我的类别文件中调用了我的新声明,该文件不包含CMMotionActivity变量。关于如何访问此功能的任何想法。这变得有些复杂,但这对我来说是最后的障碍,在我终于可以开始模拟CoreMotion数据之前。我已经模拟了陀螺仪和指南针的数据,并且已经从真实旅程中获取了数据,因此可以将其输入模拟器。但是我需要让它告诉我用户是否在走路,跑步,开车等。

有什么建议?

马特

您的方法签名override_startActivityUpdatesToQueue:withHandler:不正确。handler参数应该是一个CMMotionActivityHandler提供单个CMMotionActivity参数

typedef void (^CMMotionActivityHandler)(CMMotionActivity *activity)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章