Provided you handle the request in-place, you don't need to do anything special under MRR, since blocks themselves make const copies of the referenced values. Thus in this example the callback parameter is retained automagically (and doesn't get released until after dispatch_after's block finishes):
- (void)calculateResult:(void (^)(NSInteger))callback {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
callback(_value);
});
}
If you want to retain the callback and use it later on, then you should explicitly copy the block passed OR still copy it via synthesised properties with copy semantic:
NS_ASSUME_NONNULL_BEGIN
@interface TDWMrrObject ()
@property (copy, nonatomic, nullable) void(^callback)(NSInteger);
@property (assign, nonatomic, nullable) NSTimer *timer;
@property (assign, nonatomic) NSInteger value;
- (void)asyncCalculate;
@end
NS_ASSUME_NONNULL_END
@implementation TDWMrrObject
#pragma mark Lifecycle
- (instancetype)init {
if (self = [super init]) {
_value = 4;
}
return self;
}
- (void)dealloc {
[_callback release];
[_timer invalidate];
[super dealloc];
}
#pragma mark Actions
- (void)calculateResult:(void (^)(NSInteger))callback {
self.callback = callback;
[self asyncCalculate];
}
#pragma mark Private
- (void)asyncCalculate {
if (_timer) {
[_timer invalidate];
}
self.timer = [NSTimer scheduledTimerWithTimeInterval:4 repeats:NO block:^(NSTimer * _Nonnull timer) {
_callback(_value);
self.callback = nil;
self.timer = nil;
}];
}
@end