0

私は一定の間隔(例えば、1分に1回)でメソッドを実行する必要のあるクラスを持っています。しかし、私はこれがターゲットのライフサイクルに影響を及ぼさないようにします。言い換えれば、待っている間にターゲットを保持したくないということです。このソリューションは、メインスレッドでのみ呼び出されるため、スレッドセーフである必要はありません。今の私の解決策は、クラスがまだ機能しているかどうかを示すためにプロキシを使います。プロキシは、クラスのライフサイクルに結びついていません。ターゲットを保持せずにメソッド呼び出しを遅らせます。

//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 

BCDeathTagNSLockに置き換えることができますが、NSLockは、より高価になるととして明確に示すものではありませつもりでしょう:ここではコードです。

これは完全な解決策ですか? Cocoaの標準パターンや既存のクラス/機能を見落としていませんか?

答えて

0

問題は基本的に弱い参照をゼロにすることです。

A 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 

またNSProxyの代わりNSObjectをサブクラス化するBCObjectProxyのために可能です。 NSProxyの欠点は、その抽象クラスであり、initメソッドを持たないことです。実装サイズを2倍にすると、BCObjectProxyの2倍になります。

関連する問題