Пользовательские NSStatusItem и NSView ненадежно получают NSTrackingEvents

У меня есть приложение только в строке состояния, которое я пытаюсь отобразить на панели mouseOver. У меня есть пользовательский элемент состояния (и связанный с ним вид), подключенный и работающий, но прямоугольник отслеживания получает события только приблизительно через каждые дюжины запусков. Это заставляет меня верить, что где-то происходит гонка, но я не могу ее найти. В моем пользовательском представлении строки состояния:

- (id)initWithStatusItem:(NSStatusItem *)statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    NSLog(@"itemRect: %@", NSStringFromRect(itemRect));

    if ((self = [super initWithFrame:itemRect])) {
        _statusItem = statusItem;
        _statusItem.view = self;

        NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways;
        NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:itemRect
                                                                    options:options
                                                                      owner:self
                                                                   userInfo:nil];
        [self addTrackingArea:trackingArea];

        [self.window setIgnoresMouseEvents:NO];
        [self.window setAcceptsMouseMovedEvents:YES];

        self.wantsLayer = YES;
    }
    return self;
}

- (void)mouseEntered:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:UAStatusItemMouseEnteredNotification object:nil];
}

- (void)mouseExited:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:UAStatusItemMouseExitedNotification object:nil];
}

При большинстве запусков приложение не реагирует на отслеживание событий мыши, но время от времени mouseEntered: а также mouseExited: методы вызываются должным образом, меня полностью смущает. Что здесь происходит и что я делаю не так?




РЕДАКТИРОВАТЬ 17/17/2012
Я изменил код, основываясь на ответе @Streams, но увидел ту же проблему:

- (id)initWithStatusItem:(NSStatusItem *)statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    NSLog(@"itemRect: %@", NSStringFromRect(itemRect));

    if ((self = [super initWithFrame:itemRect])) {
        _statusItem = statusItem;
        _statusItem.view = self;            

        [self updateTrackingAreas];

        [self.window setIgnoresMouseEvents:NO];
        [self.window setAcceptsMouseMovedEvents:YES];

        self.wantsLayer = YES;
    }
    return self;
}

- (void)updateTrackingAreas {

    if (self.trackingArea)
        [self removeTrackingArea:self.trackingArea];

    [super updateTrackingAreas];

    self.trackingArea = [[NSTrackingArea alloc] initWithRect:CGRectZero
                                                     options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
                                                       owner:self
                                                    userInfo:nil];
    [self addTrackingArea:self.trackingArea];
}




РЕДАКТИРОВАТЬ 18/18/2012
Вот пример проекта barebones, который использует хорошо известный проект Github (написанный @Stream), чтобы показать проблему. Он не может получать события наведения мыши надежно, если вообще.

2 ответа

Решение

Я открыл запрос DTS, чтобы Apple взглянула на это. Вот ответ:

... вы используете полноэкранный режим в Xcode при запуске приложения. Я не делал этого [раньше], но теперь я могу воспроизвести проблему. Из того, что я могу сказать, это происходит только тогда, когда ваше приложение запускается из полноэкранного режима в XCode. Ваши пользователи не будут запускать приложение таким образом. Это проблема полноэкранного режима AppKit, а не обязательно вашего кода.

Я считаю, что вы должны управлять областями отслеживания только в -[NSView updateTrackingAreas], Например:

- (void)updateTrackingAreas
{
    if (_trackingArea) {
        [self removeTrackingArea:_trackingArea];
    }

    [super updateTrackingAreas];

    NSTrackingAreaOptions options = (NSTrackingMouseEnteredAndExited |
                                     NSTrackingMouseMoved |
                                     NSTrackingInVisibleRect |
                                     NSTrackingActiveAlways);
    _trackingArea = [[NSTrackingArea alloc] initWithRect:CGRectZero
                                                 options:options
                                                   owner:self
                                                userInfo:nil];
    [self addTrackingArea:_trackingArea];
}
Другие вопросы по тегам