代码之家  ›  专栏  ›  技术社区  ›  testing

如何避免将回调发送到已释放的实例

  •  0
  • testing  · 技术社区  · 13 年前

    以下过程导致我的应用程序崩溃:

    • 请求在后台执行
    • 用户导航回根视图

    执行以下代码

    // MyDatasource.m  
    // e.g. in connectionDidFinishLoading  
    [callback loadedDataSource:self];
    

    同时,其他模型/视图已被解除分配,消息将发送到解除分配的实例。

    callback 属于类型 id KalDataSourceCallbacks 普罗托科尔。

    如何避免将消息发送到解除分配的对象?

    this question

    编辑:

    我试着设置 回拨 dealloc 方法(在我的数据源类中)。这不能解决问题,因为 MyDataSource 释放内存 RootViewController 已发布(应用程序关闭时会发生什么情况)。

    现在 我的数据源 由我的 :

    // RootViewController.h
    @property (retain) MyDataSource *dataSource;
    
    // RootViewController.m
    @synthesize dataSource;
    // ...
    self.dataSource = [[[MyDataSource alloc] init] autorelease];
    kal.dataSource = dataSource;
    
    - (void)dealloc {
        [dataSource release];
        // ...
    }
    

    KalViewController不保留其数据源。您可能希望将对数据源的引用存储在实例变量中,以便在日历被销毁后释放它。

    我还创造了 属性:

    // MyDataSource.h
    @property (retain) id<KalDataSourceCallbacks> callback;
    
    // MyDataSource.m
    @synthesize callback;
    // ...
    - (void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate {
        // ...
        self.callback = delegate;
    }
    - (void)dealloc {
    [callback release];
    callback = nil;
       // ...
    }
    

    当前应用程序没有崩溃。我得测试一下设备。添加 callback = nil 在这里什么都不做,因为dealloc从未被调用。

    我的数据源 日历被毁后?那不起作用,因为我不知道日历是否被销毁了。所以数据源只能在整个应用程序运行时运行。

    编辑2:

    回拨 nil 想知道它是不是被释放了?

    if (callback != nil)
         [callback loadedDataSource:self];
    

    这没用。

    编辑3:

    应用程序没有崩溃,因为我保留了代理:

    @property (retain) id<KalDataSourceCallbacks> callback;
    

    应该是

    @property (assign) id<KalDataSourceCallbacks> callback;
    

    所以我怎么能避免这种方法 loadedDataSource

    3 回复  |  直到 7 年前
        1
  •  1
  •   jithinroy    13 年前

    当您移出当前视图时,请将代理设置为nil。

        2
  •  0
  •   Paul Ardeleanu    13 年前

    发送到nil对象的消息将被忽略。

        3
  •  0
  •   testing    13 年前

    KalDataSource.h 我在 KalDataSource

    @protocol KalDataSource <NSObject, UITableViewDataSource>
        // ...
        - (void)destroyCallback;
    @end
    

    KalDataSource.m

    @implementation SimpleKalDataSource
    // ...
    - (void)destroyCallback
    {
        // do nothing
    }
    @end
    

    KalViewController.m

    - (void)dealloc
    {
        // ...
        [dataSource destroyCallback];
    }
    

    MyDataSource.m 我正在实现这个功能

    - (void)destroyCallback {
        self.callback = nil;
    }