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

在委托回调方法中释放委托对象

  •  17
  • Hollance  · 技术社区  · 15 年前

    我正试图找出以下情况的推荐做法。某些对象(如CLLocationManager或MKReverseGeocoder)将其结果异步发送给委托回调方法。在回调方法中释放CLLocationManager或MKReverseGeocoder实例(或它可能是的任何类)可以吗?关键是您不再需要该对象,因此您告诉它停止发送更新,将其委托设置为nil,然后释放该对象。

    伪代码:

    @interface SomeClass <CLLocationManagerDelegate>
    ...
    @end
    
    @implementation SomeClass
    
    ...
    
    - (void)someMethod
    {
        CLLocationManager* locManager = [[CLLocationManager alloc] init];
        locManager.delegate = self;
        [locManager startUpdatingLocation];
    }
    
    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        // Do something with the location
        // ...
    
        [manager stopUpdatingLocation];
        manager.delegate = nil;
        [manager release];
    }
    
    @end
    

    我想知道这种使用模式是否被认为总是正常的,是否被认为永远不正常,或者是否取决于类?

    我一直在寻找,我找不到一个结论性的答案。有没有权威人士可以回答这个问题?

    4 回复  |  直到 15 年前
        1
  •  5
  •   JeremyP    15 年前

    Cocoa Memory Management Rules . 管理器对象作为参数传入。您没有通过“新建”、“分配”或“复制”获得它,也没有保留它。所以你 放开它。

        2
  •  5
  •   Michal    15 年前

    这是一个非常好的问题,我等了几个小时,希望有人能给出一个充分的答案,但因为没有人回答,我会尝试一下。首先,我会对你的方法进行评论,然后我会尝试建议如何解决这个问题。

    释放对象肯定是一个非常糟糕的主意——因此从其委托中释放对象。只需考虑对象(如CuloCalpMaskor)如何调用他们的委托——他们只是在某种方法的中间调用它们。当对委托的调用完成时,代码的执行返回到已经被释放的对象的方法。砰!

    让我们暂时忘记这是个坏主意这一事实。我认为有两种方法可以解决这个问题 修理 那很容易。第一, autorelease 而不是 release 给一个对象多一点时间-它至少能从委托返回中存活下来。对于大多数情况,这应该足够了,至少如果API的作者做得很好,并将逻辑封装在主API类后面(对于CLLocationManager,它可能正在等待GPS关闭…)。第二种选择是推迟发布( performSelector:withObject:afterDelay: 但对于实现糟糕的API来说,这更像是一种变通方法。

    那么,如果发布它不是一个好主意,那么它是什么呢?

    那么,通过发布一个CLLocationManager,您真正获得了什么?释放这几个字节的内存并不能避免应用程序在系统内存不足时终止。不管怎样,你真的只需要一次当前用户的位置吗?

    NSNotification ). CLLocationManager将从该类的 dealloc stopUpdatingLocation

    NSURLConnection connectionDidFinishLoading: 文件中规定“代表将不会收到更多信息”。您可以让一个类下载一堆文件,每个文件都有不同的 NSURL连接 (将您的类作为代理),在文件下载过程中分配和发布它们。

    CLLocationManager CLLocationManager

        3
  •  3
  •   twerdster    15 年前

    正如Michal所说,完全没有理由为了节省内存而发布manager对象。

    但是,正确的做法是停止更新,并将managers委托设置为nil,就像您已经在做的那样。因此,您只需要删除[manager release]行。

    我的猜测是,您正在本地范围内创建一个经理,因此正在尝试解决如何确保经理得到释放。这里正确的做法是创建一个管理器作为类的实例变量,然后在类dealloc中释放它。

        4
  •  1
  •   Kendall Helmstetter Gelner    15 年前