简体   繁体   English

NSMenuItem自定义视图未更新

[英]NSMenuItem custom view not updating

I have a NSStatusItem object which is created when the app launches (in AppDelegate.m). 我有一个NSStatusItem对象,该对象是在应用启动时创建的(在AppDelegate.m中)。 This object "_statusBarItem" has a Menu attached to it, of class statusBarMenu, which is subclass of NSMenu class but it also has a _panelItem property (of class NSMenuItem) created when you create an instance of statusBarMenu, as you can see below. 该对象“ _statusBarItem”具有一个附加的菜单,其状态为StatusBarMenu类,该菜单是NSMenu类的子类,但还具有在创建statusBarMenu实例时创建的_panelItem属性(为NSMenuItem类),如下所示。

In statusBarItem.m 在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;
}

The _panelItem has a custom view ie a clock in a label (among other things). _panelItem具有自定义视图,即标签中的时钟(除其他外)。 This view is controlled by PanelViewController class, in which when viewDidLoad method is called calls the tickTock: method shown below. 此视图由PanelViewController类控制,在该类中,调用viewDidLoad方法时将调用以下所示的tickTock:方法。 _upTime is the label showing, the clock/time. _upTime是显示的标签,时钟/时间。 It is created in the .xib file and connected 它在.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];
}

As you can see that tickTock: method is called every 1.0 second. 如您所见,tickTock:方法每1.0秒调用一次。 This is because I want the label to update, every second with new time. 这是因为我希望标签每隔新时间更新一次。 However, the label does not update even though I call setNeedsDisplay: for the PanelViewController's view. 但是,即使我为PanelViewController的视图调用setNeedsDisplay :,标签也不会更新。 I thought this might be because I might be updating the wrong view ie I should have been updating the _panelItem's view, instead. 我认为这可能是因为我可能正在更新错误的视图,即我应该一直在更新_panelItem的视图。 So I made a menuDelegate property and made statusBarMenu conform to the protocol show below. 因此,我设置了menuDelegate属性,并使statusBarMenu符合以下所示的协议。

@protocol PanelViewControllerMenuDelgate

- (void)refreshView:(id)obj;

@end

Again the refreshView: method is called every second, it updates the panel view. 再次每秒调用一次refreshView:方法,它更新面板视图。

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

However, that still does not refresh the view, and show the new label value. 但是,这仍然不会刷新视图并显示新的标签值。 I also tried itemChanged: method to the statusBarMenu obj (_statusBarItem) itself, although it did not have any different results. 我也尝试了statusBarMenu obj(_statusBarItem)本身的itemChanged:方法,尽管它没有任何不同的结果。

What I did notice is that if I close the menu (by clicking somewhere else) and re-open it, it does show the new value of the clock/label. 我注意到的是,如果关闭菜单(单击其他位置)并重新打开菜单,它会显示时钟/标签的新值。 So what am I doing wrong, or what am I not doing, that is making the view stay the same. 所以我在做什么错,或者我在做什么错,这就是使视图保持不变。 Should I be using some other procedure to make the _panelItem's view refresh every second? 我是否应该使用其他步骤使_panelItem的视图每秒刷新一次?

EDIT: 编辑:

I also noticed that the simulation stop running, when every click the _statusBarItem. 我还注意到,每次单击_statusBarItem时,模拟都会停止运行。 I simply added a NSLog statement in tickTock: method and it stopped printing in the console, when ever I open the menu. 我只是在tickTock:方法中添加了一个NSLog语句,当我打开菜单时,它就停止了在控制台中打印。 This is probably why the view is not updating, since the app/Xcode pauses when ever I click the menu. 这可能是视图未更新的原因,因为每当我单击菜单时app / Xcode都会暂停。 Why does that happen? 为什么会这样呢? Also how can I stop it? 另外我该如何阻止它?

I just came up against this problem a few weeks ago. 几周前我刚遇到这个问题。 In my case, my NSTimer was not updating my NSMenuItem . 就我而言,我的NSTimer没有更新我的NSMenuItem I believe your problem is happening because the menu is updating on a different run loop to the perform with delay. 我相信您的问题正在发生,因为菜单在不同的运行循环上进行更新以延迟执行。 This question is answered in a few places . 这个问题在几个 地方得到了回答。 But this is the code you need: 但这是您需要的代码:

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

The key is NSRunLoopCommonModes . 关键是NSRunLoopCommonModes Check out the other answers I linked to; 查看我链接到的其他答案; they already explain it really well. 他们已经很好地解释了。 That should do the trick I think. 我认为应该可以解决问题。


As a side note, neither the NSTimer nor the performSelector:withObject:afterDelay: are guaranteed to fire at exactly the time you specify. 附带说明一下, NSTimerperformSelector:withObject:afterDelay:不能保证在您指定的时间完全触发。 So if you need accuracy, do not rely on them to tell the time. 因此,如果您需要准确性,请不要依靠它们来告知时间。 If close enough is good enough, then you can ignore this note : ) 如果足够接近就足够好了,那么您可以忽略此注释:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM