3

我有一个 NSStatusItem 和一个 NSMenu 有一个委托。这个委托会根据几个因素动态更新菜单。因此,根据文档,为了快速更新菜单,我使用以下方法:

- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel;

在此方法的适当时间,我调用以下命令:

NSMenu *submenu = [[NSMenu alloc] init];
SomeSubmenuDelegate *submenuDelegate = [[SomeSubmenuDelegate alloc] init];
submenu.delegate = submenuDelegate;
item.submenu = submenu;

状态菜单显示正确,并且相应的菜单项具有子菜单的显示三角形;但是,当突出显示适当的项目时,子菜单不会出现,即使在 SomeSubmenuDelegate 中存在以下方法,根据我的经验,它应该显示三个空白菜单项:

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
{
    return 3;
}

日志也不做任何事情,甚至在 menuWillOpen 中也没有,所以看起来这些方法从未被调用过,这让我相信在某处未设置委托,或者在运行时以某种方式复制了菜单,并且在此过程中未设置委托...

目前的解决方法是在顶层 NSMenuDelegate(用于 NSStatusItem 的菜单)中创建整个子菜单,而不是分配一个委托。这里有一些缺点

1) 我将我的操作保留在 NSMenuDelegate 中,如果父菜单和子菜单有单独的文件,那就太好了。

2)虽然不一定很重要,但这意味着我在每个需要之前为每个子菜单 NSMenuItem 分配内存。

看起来最理想的是,我应该能够像使用任何其他 NSMenu 一样在这里使用委托。

非常感谢任何想法/建议。我这里的第一个问题!

编辑:这是因为 ARC 吗?我可能错误地假设按照惯例 ARC 会保留委托对象,从垃圾收集的角度考虑,但也许它被释放是因为委托是弱引用,而 ARC 没有做出这样的假设。我只能在 Apple 文档中找到对垃圾收集的引用,其中确实说垃圾收集会保持强引用......但显然,ARC 不是垃圾收集,我找不到任何关于此的信息。这意味着我需要将委托保留在父委托中,这对于如此动态的东西来说似乎很难看。有没有办法在 ARC 下保留委托,然后在适当的时间释放它,而无需在父委托(或其他任何地方)中引用它?

4

1 回答 1

0

In my case I moved the declaration of my menu instance from method to a member variable.

from

-(void)awakeFromNIb{
 ..
 [self setMenu:[[MyMenu alloc] init]];

to

 @implementation MyView{
   MyMenu *myMenu;
 }
 -(void)awakeFromNib{
   ...
  myMenu = [[MyMenu alloc]init];

  [self setMenu:[myMenu createMenuStructure]];

The method :'createMenuStructure' locally created my Menu. 'MyMenu' implements the NSMenuDelegate.

This holds the myMenu variable as a strong reference. The handler now works perfectly.

于 2014-02-16T20:30:14.157 回答