4

Objective cでコールバックと非同期コードを処理するときに、メモリ管理に問題があります。コールバックが設定されているインスタンスを解放する方法が見つからないようです。

例えば:

MyClass *myArchive = [[MyClass alloc] init]  ;
[myArchive callBack:^(RKObjectLoader* objectLoader, id object ) {

    NSLog(@"success");

} fail:^(RKObjectLoader* objectLoader, NSError* error) {

    NSLog(@"failed");


}];

[myArchive searchArchive:words:paging];

問題は、インスタンス*myArchiveをいつどのようにリリースするかがわからないことです。内のInstrumentsを使用しxcodeてコードのプロファイルを作成すると、常にここでリークが発生します。関数searchArchiveは、restkitを使用してサーバーへの非同期リクエストを実行します。これが保持サイクルを引き起こすと聞いたので、コールバック内からインスタンスを参照しません。保持サイクルを回避するために__blockや他のcアプローチを使用することについていくつか読んだことがありますが、これはすべて問題ありませんが、実際のコードが内部で発生していないためです。コールバック*myArchiveインスタンスを解放するにはどうすればよいですか。私がこれにどのように対処すべきかを説明できる人はいますobjective-cか?

編集:

これは、myclassでコールバックを設定する場所です

// Sets internal backs on this object which basically wrap the delegate 
//
- (void)callBack: (void (^)(RKObjectLoader* objectLoader, id object))success 
            fail: (void (^)(RKObjectLoader* objectLoader, NSError* error))fail {
    //sanity check
    NSAssert(_currentDelegate != self, @"Delegate is another object.  Can not set callback");

    // store our callback blocks in the instance

    _success = [success copy]  ;
    _fail = [fail copy]  ;
}

次に、deallocで_successと_failを解放します

と@interface内

@interface myClass : NSObject<RKObjectLoaderDelegate> { 
    // holds the block callback for "success"
    void (^_success)(RKObjectLoader* objectLoader, id object);
    // holds the block callback for "fail"
    void (^_fail)(RKObjectLoader* objectLoader, NSError* error);
}

これにより、私が間違っていることについてより多くの洞察が得られることを願っています。

編集2:

さて、私は今エラーを見始めています:

-(void)retrieveGallery{    

    //create call back for async and deal with the result
    [_galleryItems callBack:^(RKObjectLoader* objectLoader, NSArray *objects) {

        //success happy days. do a bunch of code here that does not cause leaks

    } fail:^(RKObjectLoader* objectLoader, NSError* error) {
        //retry the attempt to retrieve gallery data from the server 
        _retryCount++;
        if (_retryCount < _maxRetryCount) {
            [self retrieveGallery];
        }


    }];

    //read the collection of gallery items from server   
    [_galleryItems readGallery];

 }

実際のメモリリークは、コールバックが何らかの理由で失敗をキャッチし、コールバック内から[selfretrieveGallery]関数を呼び出して再試行する場合のみです。これがリークの原因になっているので、それは大したことではないと思います。関数(この場合はretrieveGallery)を再試行するにはどうすればよいですか。

4

1 に答える 1

1

非同期コールバックを使用しているため、メモリ管理に違いはありません。myArchiveこれを実行しているクラスのプロパティである必要があります。タスクが完了するまでそのままにしておきたいと思いませんか?

@property (retain) MyClass *myArchive;

それで..

myArchive = [[MyClass alloc] init];

void (^on_success_callback)(void) = ^(void){
    NSLog(@"success");
    self.myArchive = nil;
};

コールバックを適切に管理していることを確認する必要があります。つまり、コールバックをスタックからコピーし、完了したら解放します。

コードに保持とリリースがある場合は、アクセサ メソッドを適切に使用していない可能性があります。

于 2011-09-14T16:23:27.213 に答える