在不保留目标的情况下延迟方法调用

时间:2011-12-19 11:34:15

标签: objective-c cocoa memory-management grand-central-dispatch

我有一个课程需要定期执行一个方法(比如每分钟一次)。但是我不希望这会影响目标的生命周期。换句话说,我不希望在等待时保留目标。解决方案不需要是线程安全的,因为它只会在主线程上调用。到目前为止,我的解决方案使用代理来指示类是否仍然有效。代理与课程的生命周期无关。这是代码:

//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中的标准模式或现有类/功能?

1 个答案:

答案 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而不是NSObjectNSProxy的缺点是它是一个抽象类,没有init方法,添加一个会使BCObjectProxy的实现大小加倍。