2012-01-10 11 views
2

を使用するまで、デリゲートを保持:それはだから私はこのようになりますそれはこのAPIを書いて

@implementation TheApi 
    - (ObjectLoaderCallbackDelegate *)createLoaderDelegateForCallback:(ObjectLoaderCallback)callback 
    { 
     ObjectLoaderCallbackDelegate *loaderDelegate = [[ObjectLoaderCallbackDelegate alloc] init]; 
     loaderDelegate.didLoadObject = ^(id object) { 
      callback(object); 
     }; 
     return loaderDelegate; 
    } 

    - (void)loadString:(ObjectLoaderCallback)callback 
    { 
     ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback]; 
     ObjectLoader *loader = [[ObjectLoader alloc] init]; 
     [loader load:@"string" delegate:callbackDelegate]; 
    } 

    - (void)loadNumber:(ObjectLoaderCallback)callback 
    { 
     ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback]; 
     ObjectLoader *loader = [[ObjectLoader alloc] init]; 
     [loader load:@"number" delegate:callbackDelegate]; 
    } 
    @end 

私は[ローダ負荷:デリゲート:]を呼び出すと、それはへの強い参照を保持しません。デリゲート(理にかなっています)。しかし、ローダーはデリゲートを呼び出す前に非同期の処理を行うため、デリゲートが呼び出される前にデリゲートが解放され、プログラムがクラッシュします。ここに私の解決策は、(少し汚れ思われる)である:

@interface TheApi : NSObject 
    - (void)loadString:(ObjectLoaderCallback)callback; 
    - (void)loadNumber:(ObjectLoaderCallback)callback; 
    - (void)runCalls; 
    @end 

    @implementation TheApi 
    { 
     NSMutableDictionary *loaderDelegates; 
     NSMutableSet *callbacksCompleted; 
    } 

    - (TheApi *) init 
    { 
     self = [super init]; 
     if (self != nil) { 
      loaderDelegates = [[NSMutableDictionary alloc] init]; 
      callbacksCompleted = [[NSMutableSet alloc] init]; 
     } 
     return self; 
    } 

    - (void)runCalls 
    { 
     [loader runLoop]; 
    } 

    - (ObjectLoaderCallbackDelegate *)createLoaderDelegateForCallback:(ObjectLoaderCallback)callback 
    { 
     NSNumber *delegateRefKey = [NSNumber numberWithUnsignedInt:arc4random()]; 
     ObjectLoaderCallbackDelegate *loaderDelegate = [[ObjectLoaderCallbackDelegate alloc] init]; 
     loaderDelegate.didLoadObject = ^(id object) { 
      callback(object); 
      [callbacksCompleted addObject:delegateRefKey]; 
     }; 
     [loaderDelegates setObject:loaderDelegate forKey:delegateRefKey]; 
     return loaderDelegate; 
    } 

    - (void)removeCompletedDelegates 
    { 
     // So we can remove items from callbacksCompleted in the loop... 
     NSMutableSet *callbacksCompletedIterSet = [callbacksCompleted copy]; 

     // Remove old delegates for calls already completed which are stored 
     for (id key in callbacksCompletedIterSet) { 
      [loaderDelegates removeObjectForKey:key]; 
      [callbacksCompleted removeObject:key]; 
     } 
    } 

    - (void)loadString:(ObjectLoaderCallback)callback 
    { 
     [self removeCompletedDelegates]; 
     ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback]; 
     ObjectLoader *loader = [[ObjectLoader alloc] init]; 
     [loader load:@"string" delegate:callbackDelegate]; 
    } 

    - (void)loadNumber:(ObjectLoaderCallback)callback 
    { 
     [self removeCompletedDelegates]; 
     ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback]; 
     ObjectLoader *loader = [[ObjectLoader alloc] init]; 
     [loader load:@"number" delegate:callbackDelegate]; 
    } 
    @end 

だからここに、私は彼らのキーは、各APIのメソッド呼び出しのためのユニークなインスタンスレベルの辞書の代表団への参照を保持しています。

だから私の質問です:デリゲートが解放されないようにしてから、ローダーが呼び出した後に解放する方がいいですか?

+0

を参照してください?そのオブジェクトに依存している場合は、オブジェクトが終了するまで保持する必要があります。 – amleszk

答えて

0

私は最近similar questionと尋ねられ、「関連オブジェクト」について学習しました。これはあなたの問題を解決するかもしれないようです。

@CRDは彼の答えで良い説明を提供 - ローダがそのデリゲートを保持するために、なぜそれは意味がありませんhttps://stackoverflow.com/a/17351118/423565

関連する問題