[英]NSMenuItem custom view not updating
我有一個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語句,當我打開菜單時,它就停止了在控制台中打印。 這可能是視圖未更新的原因,因為每當我單擊菜單時app / Xcode都會暫停。 為什么會這樣呢? 另外我該如何阻止它?
幾周前我剛遇到這個問題。 就我而言,我的NSTimer
沒有更新我的NSMenuItem
。 我相信您的問題正在發生,因為菜單在不同的運行循環上進行更新以延遲執行。 這個問題在幾個 地方得到了回答。 但這是您需要的代碼:
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
。 查看我鏈接到的其他答案; 他們已經很好地解釋了。 我認為應該可以解決問題。
附帶說明一下, NSTimer
或performSelector:withObject:afterDelay:
都不能保證在您指定的時間完全觸發。 因此,如果您需要准確性,請不要依靠它們來告知時間。 如果足夠接近就足夠好了,那么您可以忽略此注釋:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.