我有一个课程需要定期执行一个方法(比如每分钟一次)。但是我不希望这会影响目标的生命周期。换句话说,我不希望在等待时保留目标。解决方案不需要是线程安全的,因为它只会在主线程上调用。到目前为止,我的解决方案使用代理来指示类是否仍然有效。代理与课程的生命周期无关。这是代码:
//BCDeathTag is the proxy for indicating the objects state
@interface BCDeathTag : NSObject
@property(readwrite, nonatomic, assign) BOOL isDead;
@end
@implementation BCDeathTag
@synthesize isDead = _isDead;
@end
//BCInterestingClass is where the interesting stuff happens
@interface BCInterestingClass : NSObject
@property(readonly, nonatomic) BCDeathTag *deathTag;
-(void)scheduleConsistencyCheck;
-(void)performConsistencyCheck;
...
@end
@implementation BCInterestingClass
@synthesize deathTag = _deathTag;
-(id)init
{
self = [super init];
if (self != nil)
{
_deathTag = [BCDeathTag new];
}
return self;
}
-(void)dealloc
{
_deathTag.isDead = YES;
[_deathTag release];
[super dealloc];
}
-(void)scheduleConsistencyCheck
{
__block BCInterestingClass* me = self; //prevent the block from retaining self
BCDeathTag *deathTag = self.deathTag; //but do retain the deathTag
double delayInSeconds = 60;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if (deathTag.isDead == NO)
{
[me performConsistencyCheck];
}
});
}
-(void)performConsistencyCheck
{
//Do work here
//...
[self scheduleConsistencyCheck]; //repeat the check
}
@end
BCDeathTag
可以替换为NSLock
,但NSLock
会更贵,并且不会明确表示意图。
这是一个理智的解决方案吗?我是否忽略了Cocoa中的标准模式或现有类/功能?
答案 0 :(得分:0)
问题基本上归结为弱引用。
通过用BCDeathTag
替换BCObjectProxy
(星期一清楚地表明我的病态方面)来略微改进设计:
@interface BCObjectProxy : NSObject
@property(readwrite, nonatomic, assign) id target;
@end
@implementation BCObjectProxy
@synthesize target;
@end
//BCInterestingClass is where the interesting stuff happens
@interface BCInterestingClass : NSObject
@property(readonly, nonatomic) BCObjectProxy *proxy;
-(void)scheduleConsistencyCheck;
-(void)performConsistencyCheck;
...
@end
@implementation BCInterestingClass
@synthesize proxy = _proxy;
-(id)init
{
self = [super init];
if (self != nil)
{
_proxy = [BYObjectProxy new];
_proxy.target = self;
}
return self;
}
-(void)dealloc
{
_proxy.target = nil;
[_proxy release];
[super dealloc];
}
-(void)scheduleConsistencyCheck
{
BCObjectProxy *proxy = self.proxy;
double delayInSeconds = 60;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
BCInterestingClass *me = proxy.target;
[me performConsistencyCheck];
});
}
-(void)performConsistencyCheck
{
//Do work here
//...
[self scheduleConsistencyCheck]; //repeat the check
}
@end
BCObjectProxy
也可以继承NSProxy
而不是NSObject
。 NSProxy
的缺点是它是一个抽象类,没有init
方法,添加一个会使BCObjectProxy
的实现大小加倍。