使用回调时发生内存泄漏

发布于 2024-12-04 17:01:16 字数 2416 浏览 0 评论 0原文

在处理 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。使用 xcode 中的 Instruments 来分析我的代码,我总是在这里遇到泄漏。函数 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

和 @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);
}

中释放 _success 和 _fail 的地方,我希望这能让我更深入地了解我做错了什么。

编辑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)。

I'm having an issue with memory management when dealing with callbacks and async code in objective c.
I cant seem to find a way to release the instance that the callback is set on.

For example:

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

    NSLog(@"success");

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

    NSLog(@"failed");


}];

[myArchive searchArchive:words:paging];

The problem being that I don't know when or how to release the instance *myArchive. Using Instruments within xcode to profile my code I always get a leak here. The function searchArchive performs an async request to a server using restkit. I wont reference the instance from within the callback as I heard this causes a retain cycle and I have done some reading about using __block and other c approaches to avoid retain cycles which is all fine but as it stands now with no actual code happening within the callback how do I release the *myArchive instance. anyone able to explain how I should deal with this within objective-c?

EDIT:

This is where I set the callback in 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]  ;
}

and then release _success and _fail in dealloc

and within the @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);
}

I hope this gives more insight into what I'm doing wrong.

EDIT 2:

Ok I'm beginning to see the errors now:

-(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];

 }

The only actual memory leaks are when the callback catches a fail for what ever reason and then calls the [self retrieveGallery] function from within callback to attempt again. this is what is causing the leak so I'm guessing that is a big no no. How should I attempt the function (retrieveGallery in this case) again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

零崎曲识 2024-12-11 17:01:16

内存管理实际上没有什么不同,因为您使用的是异步回调。 myArchive 应该是您在其中执行此操作的任何类的属性。您希望它一直保留到任务完成,对吗?

@property (retain) MyClass *myArchive;

然后..

myArchive = [[MyClass alloc] init];

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

您需要确保正确管理回调,即从堆栈中复制它们并在完成后释放它们。

如果您的代码中有保留和释放,您可能没有正确使用访问器方法。

Memory management isn't really any different because you are using an asynchronous callback. myArchive should be a property of whatever class you are doing this in. You want it to stick around until the task is complete, right?

@property (retain) MyClass *myArchive;

Then..

myArchive = [[MyClass alloc] init];

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

You need to make sure you are managing the callbacks properly, i.e. copying them from the stack and releasing them when you are done.

If you have retains and releases in your code you probably aren't using the accessor methods properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文