我有一个带有委托的NSMenu的NSStatusItem。该委托根据几个因素动态更新菜单。因此,根据文档,为了快速更新菜单,我使用方法:
- (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下保留委托,然后在适当的时候发布它而没有父委托中的引用(或其他任何地方)?答案 0 :(得分:0)
在我的例子中,我将菜单实例的声明从方法移动到成员变量。
来自
-(void)awakeFromNIb{
..
[self setMenu:[[MyMenu alloc] init]];
到
@implementation MyView{
MyMenu *myMenu;
}
-(void)awakeFromNib{
...
myMenu = [[MyMenu alloc]init];
[self setMenu:[myMenu createMenuStructure]];
方法:'createMenuStructure'在本地创建我的菜单。 'MyMenu'实现了NSMenuDelegate。
这将myMenu变量保存为强引用。处理程序现在完美运行。