Невозможность редактировать NSTextField в NSPopover, даже если установлено редактируемое поведение - PullRequest
20 голосов
/ 27 августа 2011

У меня есть приложение, которое открывает поповер с NSTextField. Текстовое поле не доступно для редактирования. Поведение для текстового поля установлено на Editable. Я все еще могу вставить и скопировать текст в это поле, но я не могу его редактировать

Кто-нибудь знает, что может быть не так?

Ответы [ 8 ]

38 голосов
/ 17 октября 2011

Не уверен, что вам все еще нужен ответ, но могут быть и другие, все еще ищущие. Я нашел решение на форумах разработчиков Apple. Цитирую оригинального автора:

Основная проблема заключается в том, как работают события клавиатуры. Хотя NSTextField (и все его суперпредставления) получает события клавиатуры, он не выполняет никаких действий. Это происходит из-за того, что представление, к которому подключен поповер, находится в окне, которое не может стать ключевым окном. Вы не можете получить доступ к этому окну в любом случае, по крайней мере, я не мог. Поэтому решение переопределить метод canBecomeKeyWindow для каждого NSWindow в нашем приложении, используя категорию.

NSWindow+canBecomeKeyWindow.h
@interface NSWindow (canBecomeKeyWindow)

@end

NSWindow+canBecomeKeyWindow.m
@implementation NSWindow (canBecomeKeyWindow)

//This is to fix a bug with 10.7 where an NSPopover with a text field cannot be edited if its parent window won't become key
//The pragma statements disable the corresponding warning for overriding an already-implemented method
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (BOOL)canBecomeKeyWindow
{
    return YES;
}
#pragma clang diagnostic pop

@end

Это делает поповер полностью адаптивным. Если вам нужно другое окно, которое должно отвечать NO на canBecomeKeyWindow, вы всегда можете создать подкласс.

8 голосов
/ 20 июня 2012

Я тоже некоторое время боролся с этим, пока не понял, что это ошибка.

Однако вместо того, чтобы полагаться на состояние isActive представления NSStatusItem, я считаю, что гораздо надежнее использоватьСвойство isShown реализованного вами NSPopover.

В моем коде у меня есть NSPopover в NSViewController:

  - (BOOL)canBecomeKeyWindow
    {
        if([self class]==NSClassFromString(@"NSStatusBarWindow"))
        {
            NSPopover *mainPopover = [[((AppDelegate*)[NSApp delegate]) mainViewController] mainPopover];
            if(![mainPopover isShown])
                return NO;
        }

        return YES;
    }
2 голосов
/ 07 ноября 2011

Ответ Балаза Тота работает, но если вы присоединяете всплывающее окно к NSStatusItem.view, элемент состояния перестает отвечать на запросы - для фокусировки требуется два щелчка.

1 голос
/ 17 января 2018

Если кто-то все еще ищет ответ на этот вопрос, я работаю в Swift.

В то время, когда вы хотите, чтобы поле разрешало ввод текста, я использовал myTextField.becomeFirstReponder()

Чтобы отказаться; просто используйте myTextField.resignFirstResponder()

1 голос
/ 20 декабря 2011

При работе с этим решением я обнаружил, что когда NSStatusItem перестает отвечать на запросы, вы можете легко переопределить это поведение следующим образом:

- (BOOL)canBecomeKeyWindow {
    if([self class]==NSClassFromString(@"NSStatusBarWindow")) {
        CBStatusBarView* view = [((CBAppDelegate*)[NSApp delegate]) statusItemView];
        if(![view isActive]) return NO;
    }
    return YES;
}

Вы проверите класс окна.если он соответствует NSStatusBarWindow , мы можем каким-то образом проверить, активен ли NSStatusItem .Если это так, это означает, что мы должны вернуть YES, потому что таким образом NSPopover из NSStatusItem будет иметь все события клавиатуры.

Что я использую для проверкиесли NSStatusItem был нажат (или активен), это означает, что в моем собственном пользовательском представлении у меня есть значение bool, которое изменяется, когда пользователь нажимает на NSStatusItem , система автоматически проверяет "canBecomeKeyWindow" и когда это произойдет, он вернет NO , и после того, как пользователь нажмет на него (пока он возвращает NO ), он изменит значение bool и возвращает YES при повторном запросе системы (при нажатии NSPopover для редактирования NSTextField ).

Sidenotes :

  • CBStatusBarView - это мое пользовательское представление для NSStatusItem
  • CBAppDelegate - мой класс делегата приложения
0 голосов
/ 04 августа 2018

Если кто-то получит его, а приведенное выше решение не поможет ему.Проблема в моем приложении была во вкладке info в targets мое приложение было установлено на

Application is background only = true

и должно быть

 Application is agent = true

Потратил на это целый деньвещь.

enter image description here

0 голосов
/ 01 ноября 2011

Определенно ошибка.Это сообщение об ошибке - именно то, что я пытался сделать.Даже вплоть до создания элемента статуса и переопределения mousdown.

Я могу подтвердить, что ответ Балаза Тота работает.Мне просто интересно, может ли это помешать в будущем.

0 голосов
/ 28 августа 2011
...