Question

When you have a cancel_handler for a timer, can you directly reference and reset any ivars declared as a property with 'assign' attribute or do you have to first assign it as a __block?

@interface SomeClass: NSObject { }
@property (nonatomic, assign) dispatch_source_t             timer;
@end

// Class implementation
@implementation SomeClass

@synthesize timer = _timer;
- (void)startTimer 
{
    dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 
                                    0, 0, globalQ); 

    dispatch_time_t startWhen = dispatch_walltime(DISPATCH_TIME_NOW, NSEC_PER_SEC * 1);
    dispatch_source_set_timer(_timer, startWhen, 1 * NSEC_PER_SEC, 5000ull);

    dispatch_source_set_event_handler(_timer, ^{
        // timer's event handler    
    });

    // VERSION 1:
    // Is it okay to reference and assign self.timer to nil 
    // or does it have to be declared as __block as in VERSION 2?
    dispatch_source_set_cancel_handler(_timer, ^{
        dispatch_release(_timer);                
        self.timer = nil;
    });


    // VERSION 2:
    __block myTimer = self.timer;
    dispatch_source_set_cancel_handler(_timer, ^{
        dispatch_release(myTimer);        

        myTimer = nil;
    });

    dispatch_resume(_timer);
}
Was it helpful?

Solution

You can reference ivars just fine. However, these references carry an implicit reference to self, so you need to be wary of retain cycles. For example, if you reference an ivar directly, don't expect to shut down the timer in -dealloc because that will never be called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top