Как использовать CMMotionActivityManager и получать обновления?

Я хочу создать приложение, которое может получать и обрабатывать обновления движения, чтобы понять, находится ли пользователь в неподвижном состоянии, гуляет, работает или находится в транспорте. Я видел по ссылке, что CMMotionActivityManager может быть полезен для меня.

Класс CMMotionActivityManager обеспечивает доступ к данным движения, хранящимся на устройстве. Данные о движении отражают, идет ли пользователь в течение определенного периода времени на ходьбе, беге, в транспортном средстве или в неподвижном состоянии.

Я новичок в разработке приложений и не понимаю, как использовать метод для запуска обновления. Метод для этого - (void)startActivityUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMMotionActivityHandler)handler, Я не понимаю, что я должен написать на обработчик, потому что ссылка говорит:

handler Блок для выполнения при обнаружении изменения в текущем типе движения. Для получения информации о параметрах этого блока, см. CMMotionActivityHandler. Это свойство не должно быть нулевым.

Моя реализация:

- (IBAction)startButtonPressed:(id)sender {
_motionActivityManager = [[CMMotionActivityManager alloc] init];
[_motionActivityManager startActivityUpdatesToQueue:NSOperationQueueDefaultMaxConcurrentOperationCount withHandler:CMMotionActivityHandler];
}

Я уже импортировал инфраструктуру CoreMotion, но XCode не распознает CMMotionActivityHandlerгде я не прав? Как я могу решить эту проблему?

Спасибо

5 ответов

Получившая наибольшее количество голосов версия этого ответа является немного окольными. Он создает очередь, но затем использует GCD для выполнения обратно в основную очередь. Кроме того, многие примеры помещают блок в withHandler параметр, но я нахожу это неуклюжим и выглядит не так чисто (с точки зрения форматирования кода).

Вот мой пример реализации:

@implementation MotionHandler {
@private
    // this is a private variable for this class that is not visible outside
    // (also, iOS handles memory and access management of these faster than properties)
    CMMotionActivityManager *_motionActivityManager;
}

// initialization method, you can do other stuff here too
- (instancetype)init {
    self = [super init];
    if (self) {
        // check to see if the device can handle motion activity
        if ([CMMotionActivityManager isActivityAvailable]) {
            // if so, initialize the activity manager
            _motionActivityManager = [[CMMotionActivityManager alloc] init];
        }
    }
}

- (void)startMotionActivityMonitoring {
    // create the motion activity handler
    CMMotionActivityHandler motionActivityHandler = ^(CMMotionActivity *activity) {
         // TODO motion detected here. Do something.
    }

    // check to see if the motion activity manager exists
    if (_motionActivityManager) {
        // if so, start monitoring activity
        // notice that we add updates to the mainQueue. This will call your handler on the main thread
        [_motionActivityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:motionActivityHandler];
    }
}

@end

Образец кода:

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

         dispatch_async(dispatch_get_main_queue(), ^{

             if ([activity walking]) {
                 NSLog(@"walking");
             }
     });
}];

Swift 2.0

_motionActivityManager = CMMotionActivityManager()   
_motionActivityManager.startActivityUpdatesToQueue(NSOperationQueue.mainQueue())
{
    // CMMotionActivity
    activity in

    // do your logic here

}

// проверить, доступно ли на устройстве

BOOL b=  [CMMotionActivityManager isActivityAvailable];;

motionActivityManager=[[CMMotionActivityManager alloc]init];
//register for coremotion notification

 [motionActivityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMMotionActivity *activity) {

    NSLog(@"Got a core motion update");
    NSLog(@"Current activity date is %f",activity.timestamp);
    NSLog(@"Current activity confidence from a scale of 0 to 2 - 2 being best- is: %ld",activity.confidence);
    NSLog(@"Current activity type is unknown: %i",activity.unknown);
    NSLog(@"Current activity type is stationary: %i",activity.stationary);
    NSLog(@"Current activity type is walking: %i",activity.walking);
    NSLog(@"Current activity type is running: %i",activity.running);
    NSLog(@"Current activity type is cycling: %i",activity.cycling);
    NSLog(@"Current activity type is automotive: %i",activity.automotive);



}];

Пожалуйста, проверьте на устройстве

-(void)device_motion{

    self.motionManager= [[CMMotionManager alloc]  init];
    self.motionManager.deviceMotionUpdateInterval = 1.0/60.0;
    self.opQ = [NSOperationQueue currentQueue];

    if(self.motionManager.isDeviceMotionAvailable)
    {

        // Listen to events from the motionManager
        self.motionHandler = ^ (CMDeviceMotion *motion, NSError *error)
        {
            if (!prevTime)
            {
                prevTime = motion.timestamp;
                return;
            }

            //Calculate delta time between previous motionUpdate call and _now_
            double deltaTime = motion.timestamp - prevTime;
            prevTime = motion.timestamp;

            //Y axis rotation
            CMRotationRate rotationRate = motion.rotationRate;
            double rotation = rotationRate.y;

            if (fabs(rotation) < 0.05) //igonre bias
                return;

            //Calculate the angular distance
            double anglePathRad = rotation * deltaTime;

            //calculate total panoram angle
            currAngle += CC_RADIANS_TO_DEGREES(anglePathRad);

            NSLog(@"Angle : %f ",currAngle);


        };

    } else {
        NSLog(@"No Device Motion on device.");
    }

    // Start listening to motionManager events
    [self.motionManager startDeviceMotionUpdatesToQueue:self.opQ withHandler:self.motionHandler];


}
Другие вопросы по тегам