3

Using my 6+ I've been trying to read the relative altitude and pressure using CoreMotion's new CMAltimeter. However the callback is never firing. I have a very similar setup which instead uses the accelerometers, gyros, and magnetometers. They all seem to work fine.

Was wondering if anyone out there has managed to get a reading?

- (void)viewDidLoad {
    [super viewDidLoad];

    if([CMAltimeter isRelativeAltitudeAvailable]){
        CMAltimeter *altimeterManager = [[CMAltimeter alloc]init];
        [altimeterManager startRelativeAltitudeUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAltitudeData *altitudeData, NSError *error) {
            // This never fires.
            NSString *data = [NSString stringWithFormat:@"Altitude: %f %f", altitudeData.relativeAltitude.floatValue, altitudeData.pressure.floatValue];
            NSLog(@"%@", data);
            self.altimeterLabel.text = data;
        }];
        NSLog(@"Started altimeter");
        self.altimeterLabel.text = @"-\n-";
    } else {
        NSLog(@"Altimeter not available");
    }
}

I've tried taking this on a quick walk, but there's only one story of altitude to lose/gain around here.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
VaporwareWolf
  • 10,143
  • 10
  • 54
  • 80
  • Don't have the hardware to try this myself, but a couple ideas: 1) try sending updates to a background queue instead of the main queue? 2) get some more altitude — try model rocketry? :) – rickster Sep 25 '14 at 04:11
  • Yeah, I've tried using background queues as well with the same result. The documentation says it should update every few minutes, but I've never seen it update. Still haven't walked up a hill though.... – VaporwareWolf Sep 27 '14 at 06:09

2 Answers2

10

I'm pretty embarrased to answer my own question with such a huge oversight.

In the original post I had the CMAltimiter declared in the scope of viewDidLoad, thus it goes out of scope and is deallocated. I moved it to be an iVar and the callback now fires.

#import "ViewController.h"
@import CoreMotion;

@interface ViewController ()
@property (nonatomic, strong) CMAltimeter *altimeterManager;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    if([CMAltimeter isRelativeAltitudeAvailable]){
        self.altimeterManager = [[CMAltimeter alloc]init];
        [self.altimeterManager startRelativeAltitudeUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAltitudeData *altitudeData, NSError *error) {
            // This now fires properly
            NSString *data = [NSString stringWithFormat:@"Altitude: %f %f", altitudeData.relativeAltitude.floatValue, altitudeData.pressure.floatValue];
            NSLog(@"%@", data);
            self.altimeterLabel.text = data;
        }];
        NSLog(@"Started altimeter");
        self.altimeterLabel.text = @"-\n-";
    } else {
        NSLog(@"Altimeter not available");
    }
}
VaporwareWolf
  • 10,143
  • 10
  • 54
  • 80
  • I had this similar situation when using CoreLocation's CLLocationManager class,and place it as an ivar solves the problem.I think it is time to review ARC lesson.-:] – tounaobun Mar 22 '15 at 01:48
-3

You need to call [altimeterManager stopRelativeAltitudeUpdates]; for the references to be released to the dispatch queue.

lennon310
  • 12,503
  • 11
  • 43
  • 61