objective-c - 更新 NSMenu 中的项目时的内存管理

标签 objective-c cocoa memory-management memory-leaks 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];
}

如您所见,在添加新项目之前,我会删除所有以前的项目并向它们发送 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];
}

请注意,通过在下层循环中创建 NSMenuItem 期间添加 autorelease,无需发送额外的 release在菜单项删除过程中,就像您的代码中一样。从某种意义上说,NSMenu 的作用类似于 NSArray 对其包含的子菜单和菜单项的作用:它保留它们。因此,由于您将新创建的 NSMenuItem 直接插入到 NSMenu 中,就好像 NSMenu 正在获取菜单项的所有权。因此,您需要抵消从项目的 alloc/init 创建中获得的 +1 保留计数,以确保不会发生内存泄漏。在您的代码中,您通过在菜单项删除期间向其发送显式/额外释放来抵消 +1 保留计数,这是一种迂回。在我发布的上面的代码中,通过在下部循环的创建过程中添加 autorelease ,唯一“保留”菜单项的就是菜单。然后,稍后,当您调用 removeAllItems 方法时,菜单将向每个菜单项发送 release,此时它们的保留计数应降至 0,并且它们'将被释放。

如果您需要支持 10.6 之前的 OS X 版本,可以使用上述代码,但需要用 [statusMenuScansMenu md_removeAllItems] 替换 [statusMenuScansMenu removeAllItems]。然后,您可以在 NSMenu 上的类别中创建此 md_removeAllItems 方法,如下所示:

@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

关于objective-c - 更新 NSMenu 中的项目时的内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7694042/

相关文章:

ios - 如何使用 iOS8+ 的 Objective-C 从 URL 下载照片并添加到特定相册?

ios - 代码 : Storyboard and state preservation of the view controllers after quitting

c++ - 在运行时确定 std::map/std::set 的内存使用

ios - 相对 NSDate 与结果 TheDayBeforeYesterday,Yesterady,Today,Tomorrow

html - 如何在 UIWebView 中显示 HTML 代码?

cocoa - 使用 Sketch 插件添加新画板

objective-c - 更改事件和非事件 NSTextField 的文本颜色

iphone - 使用可达性互联网*或*本地 WiFi?

c - 应用程序内存优化

windows - 调用_freea 真的有必要吗?