如何允许在回调时释放对象?

Posted

技术标签:

【中文标题】如何允许在回调时释放对象?【英文标题】:How to allow the object to be released on callback? 【发布时间】:2011-01-16 13:09:57 【问题描述】:

我有一个用 Objective C 编写的类,它通过连接到网络来完成一些工作。此类以异步方式完成此工作,并且用户提供了一个委托,该委托在操作完成后被调用(如果成功则响应,如果失败则返回错误)。当没有更多工作要做并且可以释放对象时调用委托。

现在我想支持一个用例,当用户在对该委托的调用中释放我的类的对象时。这是很自然的,因为我的类的实例不可重用。目前,当我的调用从回调返回时,它会尝试从离开的地方继续,却发现它已被释放。不用说,此时应用程序崩溃了。

我知道这是可以做到的,因为NSURLConnection class 就是这样做的。在回调- (void)connectionDidFinishLoading:(NSURLConnection *)connection 中释放连接对象即可。我怎样才能做到这一点?

编辑:

下面是更好理解的代码:

@class MyRequest;

@protocol MyDelegate

- (void)completedRequest:(MyRequest*)request;

@end

@interface MyRequest : NSObject 
    id<MyDelegate> myDelegate;
    //variables...


- (id)init;
- (id)initWithUrl:(NSString*)url delegate:(id<MyDelegate>)delegate;
- (void)dealloc;

- (void)fire;

@property (nonatomic, readonly) bool fired;
@property (nonatomic, readonly) NSInteger resultCode;
@property (nonatomic, readonly) NSString *errorMessage;

@end

用户创建MyRequest 的对象并发送fire 消息。 MyRequest 在内部使用 NSURLConnection 来完成这项工作。收到响应后,我调用用户给定的委托。

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

    NSLog(@"In connectionDidFinishLoading...");

    resultCode = RESULT_SUCCESS;
    [urlConnection release];
    [urlRequest release];

    if (myDelegate != nil)
        [myDelegate completedRequest:self];

【问题讨论】:

【参考方案1】:

只需在调用委托回调之前添加[[self retain] autorelease] 即可延长对象的生命周期。这将导致它稍后发布,以便您完成。

另一种方法是使用NSObjectperformSelectorOnMainThread 方法。 performSelector...机械会保留你的对象,调用方法,然后释放它。如果您让 performSelector 方法等到完成,那么您将遇到与现在相同的问题,因为您将在该调用期间被释放。如果您不等到它完成,那么您不应该有内存问题,但是完成后您将无能为力。如果这是可以接受的,那么你应该没问题。

【讨论】:

可以工作!在寻找线索时,我遇到了方法performSelectorOnMainThread,它可用于调度方法调用。能解决问题吗? 这也可以解决你的问题,因为performSelector... 机器会保留你的对象,调用方法,然后释放它。如果您让performSelector 方法等到完成,那么您将遇到与现在相同的问题,因为您将在该调用期间被释放。如果您不等到它完成,那么您不应该有内存问题,但是完成后您将无能为力。如果这是可以接受的,那么你应该没问题。 我冒昧地根据您的 cmets 更新了答案。它使答案完整,我可以愉快地接受它。希望你不要介意。 完全没有 - 我正在考虑自己进行修改。

以上是关于如何允许在回调时释放对象?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript:如何在回调中设置父对象变量

带有按钮回调的新窗口未在 fltk 中打开

MTAudioProcessingTap EXC_BAD_ACCESS ,并不总是触发 finalize 回调。如何释放它?

Bean的初始化回调方法和释放资源的回调方法

Bean的初始化回调方法和释放资源的回调方法

用户不允许权限时的CMMotionActivityManager回调