0

New iOS developer here. I've been searching for an answer to this in documentation on blocks and the altimeter, but I'm coming up short. I assume there's some simple thing I'm missing, but can't figure it out.

I have a custom class called PressureSensor. Simplistically speaking, the class has a property:

@property (nonatomic, strong, readwrite) NSMutableArray *pressure;

I load NSNumber values from the altimeter into this array.

The initializer for the class is:

- (instancetype)init
{
    self = [super init];

    if (self)
    {
        if (self.altimeterIsAvailable)
        {
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];
            [self.altimeter startRelativeAltitudeUpdatesToQueue:queue withHandler:^(CMAltitudeData *altitudeData, NSError *error) {
                dispatch_async(dispatch_get_main_queue(), ^ {

                    [self.pressure addObject:altitudeData.pressure];

                    NSLog(@"Pressure 1: %@", [self.pressure lastObject]);
                });
            }];
            NSLog(@"Pressure 2: %@", [self.pressure lastObject]);
        }
    }
    return self;
}

When I run the app on my phone, I assume that pressure is successfully added to the self.pressure array, because the pressure is printed to the console by the "Pressure 1" line, which accesses the lastObject of self.pressure. However, it seems that these changes don't hold outside this block, as the Pressure 2 line outputs (null) to the console, and it doesn't seem like I can do anything with self.pressure outside this block.

Am I missing something about how blocks work exactly? Do I just need a __block somewhere? I'm completely at a loss here.

Addendum: self.altimeterIsAvailable is defined elsewhere. That part of the code shouldn't have any issues.

EDIT: The error ended up being elsewhere. For future readers who browse this post, the above code should be a perfectly valid way to add to a property array in a block.

surrix
  • 11
  • 2
  • 1
    startRelativeAltitudeUpdatesToQueue:withHandler: is an asynchronous method, and like all asynchronous methods, it returns immediately, before the call back to its handler, so your log outside the method (@"Pressure 2") is printed before the readings get updated. – rdelmar Dec 21 '14 at 05:19
  • I thought it might have something to do with the asynchronicity of the method, but I don't think that's the whole story. No matter how long I run it, Pressure 2 always prints out (null) even if there are hundreds of successful Pressure 1 calls above it in the console. Furthermore, if I print out [self.pressure count] outside the block, it returns 0 as well. – surrix Dec 21 '14 at 05:37
  • How and where are you instantiating the mutable array? When you let it run a long time does the "Pressure 2" log print more than once? – rdelmar Dec 21 '14 at 05:43
  • Just found my issue, it was actually in the View Controller. I was missing if (!_pressureSensor) in the getter for the sensor in the View Controller, so it was reallocing every time. I think pressures are now being written to the pressure array. Thank you for your help! – surrix Dec 21 '14 at 05:53

1 Answers1

0

This is not an answer but I'd like to mention it.

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[self.altimeter startRelativeAltitudeUpdatesToQueue:queue withHandler:^(CMAltitudeData *altitudeData, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^ {
        ...
    });
 }];

Creating a queue, and dispatch_async to the main queue. It's redundant. You can use NSOperationQueue +mainQueue method for it directly.

NSOperationQueue *queue = [NSOperationQueue mainQueue];
[self.altimeter startRelativeAltitudeUpdatesToQueue:queue withHandler:^(CMAltitudeData *altitudeData, NSError *error) {
    ...
}];
Kazuki Sakamoto
  • 13,929
  • 2
  • 34
  • 96