有許多Foundation類允許您提供一個指向void的指針,該指針稍後作爲參數傳遞給回調函數。例如,addKeyserver:forKeyPath:options:context:of NSKeyValueObserving。與可可中的void *上下文相關的內存管理
由於指向void的指針可能無法擴展NSObject,因此接受此類參數的函數不能期望保留它。因此,您的代碼必須看起來類似於以下內容:
- (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
}
這是有道理的,但它似乎違背了可可/ Objective-C的對象所有權的每一個原則。另外,如果你忘記在這種情況下手動管理內存,它經常(儘管不總是)導致EXC_BAD_ACCESS崩潰。此外,Xcode分析器抱怨。
我問這個問題的原因是因爲我正在編寫一個網絡連接庫,在其公共API中使用相同類型的上下文指針。然而,在我自己的代碼中需要跟蹤一些內存管理錯誤,這些錯誤與所需的手動內存管理有關,我相信必須有更好的方法。一種解決方案是將API的上下文參數類型更改爲(id <NSObject>),而不是(void *)。
爲什麼Foundation類經常使用(void *)而不是(id <NSObject>)?