我有一个向串行 NSOperationQueue 添加操作的方法。由于我想定期调用该方法,因此我使用调度源计时器。
但是,也可以响应用户操作调用此方法。当这种情况发生时(例如,由于计时器调用方法之前的片刻),我会延长计时器的触发日期。
问题是我写的代码有一个保留周期,我不明白在哪里。
这是演示问题的简化示例(不要忘记将部署 SDK 设置为 10.7):
#import <Foundation/Foundation.h>
@interface MyObject : NSObject
@end
@implementation MyObject
{
NSOperationQueue *_queue;
dispatch_source_t _timer;
}
- (id)init
{
self = [super init];
if (self)
{
_queue = [[NSOperationQueue alloc] init];
[_queue setMaxConcurrentOperationCount:1];
}
return self;
}
- (void)dealloc
{
NSLog(@"dealloc");
[_queue cancelAllOperations];
dispatch_source_cancel(_timer);
dispatch_release(_timer);
}
- (void)scheduleTimer
{
if (_timer)
{
dispatch_source_cancel(_timer);
dispatch_release(_timer);
}
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0,
0,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
if (_timer)
{
__weak MyObject *selfBlock = self;
dispatch_source_set_event_handler(_timer, ^{
dispatch_source_cancel(_timer);
[selfBlock doMethod];
});
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 0);
dispatch_resume(_timer);
}
}
- (void)doMethod
{
NSLog(@"doMethod");
__weak MyObject *selfBlock = self;
[_queue cancelAllOperations];
[_queue addOperationWithBlock:^{
[selfBlock scheduleTimer];
}];
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
MyObject *obj = [MyObject new];
[obj doMethod];
sleep(10);
obj = nil;
NSLog(@"something still points to obj");
sleep(10);
}
return 0;
}