NSMenuItem自定义视图不更新

时间:2014-11-18 17:02:49

标签: objective-c xcode macos nsmenu nsstatusitem

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

在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];
}

正如您所看到的,每隔1.0秒调用一次tickTock:方法。这是因为我希望标签能够以新的时间每秒更新一次。但是,即使我调用setNeedsDisplay:对于PanelViewController的视图,标签也不会更新。我认为这可能是因为我可能正在更新错误的视图,即我应该更新_panelItem的视图。所以我创建了一个menuDelegate属性,并使statusBarMenu符合下面的协议。

@protocol PanelViewControllerMenuDelgate

- (void)refreshView:(id)obj;

@end

每秒都会调用refreshView:方法,它会更新面板视图。

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

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

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

修改

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

1 个答案:

答案 0 :(得分:0)

几周前我刚刚遇到了这个问题。在我的情况下,我的NSTimer没有更新我的NSMenuItem。我相信你的问题正在发生,因为菜单正在以不同的运行循环更新到延迟执行。这个问题已在few places中得到解答。但这是您需要的代码:

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: 保证都不会在您指定的时间触发。因此,如果您需要准确性,请不要依赖它们来说明时间。如果足够接近足够好,那么你可以忽略这个注释:)