与Cocoa中的void *上下文相关的内存管理 [英] Memory management related to void* context in Cocoa

查看:64
本文介绍了与Cocoa中的void *上下文相关的内存管理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有许多Foundation类,允许您提供指向void的指针,该指针在以后作为参数传递给回调函数.例如,NSKeyValueObserving的addObserver:forKeyPath:options:context:.

There are a number of Foundation classes that allow you to provide a pointer to void that is passed as an argument to a callback function at a later time. For instance, addObserver:forKeyPath:options:context: of NSKeyValueObserving.

由于指向void的指针可能不会扩展NSObject,因此不能期望接受此类参数的函数保留该参数.因此,您的代码必须类似于以下内容:

Since a pointer to void may not extend NSObject, functions which accept such an argument cannot be expected to retain it. Therefore, your code must look similar to the following:

- (void)sharedInit
{
    MyObject *myObject = [[MyObject alloc] init];
    [x addObserver:y forKeyPath:@"z" options:0 context:myObject];
    // cannot (auto)release myObject here
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    MyObject *myObject = (MyObject *)context;
    [myObject release]; // myObject is released here
}

这很有意义,尽管它似乎违反了Cocoa/Objective-C对象所有权的所有原则.此外,如果您忘记了在这种情况下手动管理内存,则经常(尽管并非总是如此)会导致EXC_BAD_ACCESS崩溃.此外,Xcode分析器抱怨.

This makes sense, although it seems to violate every principle of Cocoa/Objective-C object ownership. In addition, if you forget to manually manage memory in such a case it often (although not always) results in a EXC_BAD_ACCESS crash. Furthermore, the Xcode analyzer complains.

之所以问这个问题,是因为我正在编写一个网络连接库,该库在其公共API中使用了相同类型的上下文指针.但是,在不得不在我自己的代码中查找与导致对手动内存管理的需求相关的许多内存管理错误之后,我相信必须有更好的方法.一种解决方案是将我的API的上下文参数的类型更改为(id< NSObject>),而不是(void *).

The reason I am asking this question is because I am writing a network connection library that makes use of the same sort of context pointers in its public API. However, after having had to track down a number of memory management bugs in my own code related to the resulting need for manual memory management, I believe there must be a better way. One solution is to change the types of the context arguments of my API to (id<NSObject>) rather than (void*).

为什么Foundation类经常使用(void *)而不是(id< NSObject>)?

Why do Foundation classes often use (void*) rather than (id<NSObject>)?

推荐答案

MHC关于推理是正确的.不需要对象是NSObject.但是,您注意到,无论如何您在这里都无法正确执行内存管理.

MHC is correct about the reasoning. There is no requirement that the object be an NSObject. But you are doing your memory management incorrectly here in any case, as you note.

在这种情况下,管理对象的常用模式不是将对象泄漏然后尝试清除它,而是将其存储为注册类的ivar.另一个常见的模式是将self作为上下文传递,确保在-dealloc期间取消注册回调.

Rather than leaking an object, and then trying to clean it up later, the common pattern for managing an object in this case is to store it as an ivar of the registering class. Another common pattern is to pass self as the context, making sure to unregister for callbacks during -dealloc.

这篇关于与Cocoa中的void *上下文相关的内存管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆