NSMenuItem 自定义视图未更新

Posted

技术标签:

【中文标题】NSMenuItem 自定义视图未更新【英文标题】:NSMenuItem custom view not updating 【发布时间】:2015-01-15 23:12:57 【问题描述】:

我有一个 NSStatusItem 对象,它是在应用程序启动时创建的(在 AppDelegate.m 中)。这个对象“_statusBarItem”附有一个菜单,属于 statusBarMenu 类,它是 NSMenu 类的子类,但它还具有在创建 statusBarMenu 实例时创建的 _panelItem 属性(属于 NSMenuItem 类),如下所示。

在statusBarItem.m中

- (instancetype)initWithTitle:(NSString *)aTitle
self = [super initWithTitle:aTitle];

if (self)

    _panelItem = [[NSMenuItem alloc]init];
    PanelViewController *panelViewController = [[PanelViewController alloc]init];
    panelViewController.menuDelegate = self;
    _panelItem.view = panelViewController.view;

    [self addItem:_panelItem];

return self;

_panelItem 有一个自定义视图,即标签中的时钟(除其他外)。该视图由 PanelViewController 类控制,其中调用 viewDidLoad 方法时会调用如下所示的 tickTock: 方法。 _upTime 是显示的标签,时钟/时间。它在 .xib 文件中创建并连接

- (void)tickTock:(id)obj
NSTimeInterval timeInterval = 7.5 * 60 * 60;

NSDate *timeToGetUp = [NSDate dateWithTimeInterval:timeInterval sinceDate:[NSDate date]];

NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:@"hh:mm:ss"];

[_upTime setStringValue:[dateFormatter stringFromDate:timeToGetUp]];

[self.view setNeedsDisplay:YES];
[self.menuDelegate refreshView:self];

[self performSelector:@selector(tickTock:) withObject:NULL afterDelay:1.0];

如您所见,tickTock: 方法每 1.0 秒调用一次。这是因为我希望标签更新,每一秒都有新的时间。但是,即使我为 PanelViewController 的视图调用 setNeedsDisplay:,标签也不会更新。我认为这可能是因为我可能更新了错误的视图,即我应该更新 _panelItem 的视图,而不是。所以我做了一个 menuDelegate 属性,并让 statusBarMenu 符合下面显示的协议。

@protocol PanelViewControllerMenuDelgate

- (void)refreshView:(id)obj;

@end

refreshView: 方法每秒被调用一次,它更新面板视图。

- (void)refreshView:(id)obj
[_panelItem.view setNeedsDisplay:YES];
//    [self itemChanged:_panelItem];

但是,这仍然没有刷新视图,并显示新的标签值。我还尝试了 statusBarMenu obj (_statusBarItem) 本身的 itemChanged: 方法,尽管它没有任何不同的结果。

我注意到的是,如果我关闭菜单(通过单击其他位置)并重新打开它,它会显示时钟/标签的新值。所以我做错了什么,或者我没有做什么,就是让视图保持不变。我是否应该使用其他程序来使 _panelItem 的视图每秒刷新一次?

编辑:

我还注意到模拟停止运行时,每次单击_statusBarItem。我只是在 tickTock: 方法中添加了一个 NSLog 语句,当我打开菜单时它会停止在控制台中打印。这可能是视图没有更新的原因,因为当我单击菜单时应用程序/Xcode 会暂停。为什么会这样?还有我怎么能阻止它?

【问题讨论】:

【参考方案1】:

几周前我刚刚遇到了这个问题。就我而言,我的NSTimer 没有更新我的NSMenuItem。我相信您的问题正在发生,因为菜单在不同的运行循环上更新以延迟执行。这个问题在fewplaces 中得到了回答。但这是您需要的代码:

NSTimer interfaceUpdateTimer = [NSTimer timerWithTimeInterval:self.timerSettings.timerUpdateInterval//one second in your case
                                         target:self
                                                  selector:@selector(tickTock:)
                                       userInfo:nil
                                        repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:interfaceUpdateTimer forMode:NSRunLoopCommonModes];

密钥是NSRunLoopCommonModes。查看我链接到的其他答案;他们已经很好地解释了。我认为这应该可以解决问题。


附带说明,NSTimerperformSelector:withObject:afterDelay:保证在您指定的时间触发。因此,如果您需要准确性,请不要依赖他们来告诉时间。如果足够接近就足够好,那么您可以忽略此注释:)

【讨论】:

以上是关于NSMenuItem 自定义视图未更新的主要内容,如果未能解决你的问题,请参考以下文章

具有自定义视图的 NSMenuItem 不接收鼠标事件

具有自定义视图的 NSMenuItem 在滚动时消失

如何删除自定义视图上方的 NSMenuItem 间隙

自定义 UILabel 视图未在 Interface Builder 中更新其框架

didEndEditingRowAt 未使用自定义表格视图单元格调用

自定义视图中未调用 UIButton 操作