Задержка вызова метода без сохранения цели - PullRequest
0 голосов
/ 19 декабря 2011

У меня есть класс, который должен выполнять метод через равные промежутки времени (скажем, раз в минуту).Однако я не хочу, чтобы это влияло на жизненный цикл цели.Другими словами, я не хочу, чтобы цель сохранялась во время ожидания.Решение не должно быть потокобезопасным, поскольку оно будет вызываться только в основном потоке.Мое решение до сих пор использует прокси, чтобы указать, все ли класс функционирует.Прокси не привязан к жизненному циклу класса.Вот код:

//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 будет более дорогим и не будет указывать намерение так же ясно.

Является ли этовменяемое решение?Я пропускаю стандартный образец или существующий класс / функциональность в Какао?

1 Ответ

0 голосов
/ 20 декабря 2011

Проблема, по сути, заключается в обнулении слабых ссылок.

Немного улучшен дизайн, заменив 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

ItBCObjectProxy также может быть подклассом NSProxy вместо NSObject.Недостатком NSProxy является то, что он является абстрактным классом и не имеет метода init, добавление которого удвоит размер реализации BCObjectProxy.

...