Dan*_*iel 1 cocoa memory-leaks memory-management objective-c nsmenu
我想知道这是否是在Cocoa应用程序中避免内存泄漏的正确方法.
我的应用程序有一个更新NSMenu项目的方法:
//Remove and Release old Status Scan Menu:
if ([statusMenuScansMenu numberOfItems] !=0) {
for (NSMenuItem *menueItemToBeReleased in [statusMenuScansMenu itemArray]) {
[statusMenuScansMenu removeItem:menueItemToBeReleased];
[menueItemToBeReleased release];
}
}
//New Status Scan Menu:
for (MyObject* myObject in myArray) {
NSMenuItem * scanMenuItem = [[NSMenuItem alloc] init];
[scanMenuItem setTitle:[myObject name]];
[statusMenuScansMenu addItem:scanMenuItem];
}
Run Code Online (Sandbox Code Playgroud)
如您所见,在添加新项目之前,我删除所有以前的项目并发release送给他们.然后我添加新的.
这是内存管理的最佳方式吗?
如果我在Xcode 4.1中分析我的代码,它会说存在潜在的内存泄漏.
它看起来像你在做它可能工作正常,但它是一种奇怪的方式来解决它.
如果您可以要求OS X 10.6+,您的代码可以合并到以下内容:
//Remove old Status Scan Menu:
[statusMenuScansMenu removeAllItems];
//New Status Scan Menu:
for (MyObject* myObject in myArray) {
NSMenuItem * scanMenuItem = [[[NSMenuItem alloc]
initWithTitle:[myObject name] action:NULL keyEquivalent:@""] autorelease];
[statusMenuScansMenu addItem:scanMenuItem];
}
Run Code Online (Sandbox Code Playgroud)
请注意,通过在下部循环中autorelease创建期间添加a NSMenuItem,无需release像在代码中那样在菜单项删除期间发送额外内容.从某种意义上说,NSMenu它就像NSArray它包含的子菜单和菜单项一样:它保留它们.因此,由于您NSMenuItem直接将新创建的内容插入其中NSMenu,就好像NSMenu它取得了菜单项的所有权一样.因此,您需要抵消从项目的alloc/init创建中获得的+1保留计数,以确保不会出现内存泄漏.在您的代码中,您通过在菜单项删除期间向其发送显式/额外版本来抵消+1保留计数,这是一种迂回曲折.在我发布的上面的代码中,通过autorelease在下循环中创建期间添加,菜单中唯一"保持"菜单项.然后,稍后,当您调用该removeAllItems方法时,菜单将向release每个菜单项发送一个,此时它们的保留计数应该降为0,并且它们将被取消分配.
如果您需要支持10.6之前的OS X版本,则可以使用上述代码,但替换[statusMenuScansMenu md_removeAllItems]为[statusMenuScansMenu removeAllItems].然后,您可以md_removeAllItems在类别中创建此方法,NSMenu如下所示:
@interface NSMenu (MDAdditions)
- (void)md_removeAllItems;
@end
@implementation NSMenu (MDAdditions)
- (void)md_removeAllItems {
NSUInteger currentCount = [self numberOfItems];
for (NSUInteger i = 0; i < currentCount; i++) {
[self removeItemAtIndex:0];
}
}
@end
Run Code Online (Sandbox Code Playgroud)