Почему мигающий курсор в текстовом поле вызывает вызов drawRect?

У меня есть следующая настройка иерархии представлений в моей программе.

Window
+ContentView (Subview of Window)
++MyCustomView (Subview of ContentView)
++MyCustomOpaqueView (Subview of ContentView)
+++TextField (Subview of MyCustomOpaqueView)

Когда пользователь щелкает TextField, курсор внутри него начинает мигать. При каждом моргании вызывается метод drawRect для MyCustomView. Ничего страшного, но мне интересно, почему?

В MyCustomOpaqueView я реализую isOpaque так,

- (BOOL)isOpaque {return YES;}

Я думал, что это заблокирует сообщения для drawRect в MyCustomView, если NSRect, переданный в drawRect, полностью закрыт непрозрачным представлением, но когда курсор мигает, MyCustomView по-прежнему получает сообщение drawRect с NSRect полностью за непрозрачным представлением.

Я пропустил ключевую концепцию или это причуда мигающего курсора?



person Tobias    schedule 09.03.2011    source источник
comment
+1: Хорошее расследование! Поскольку вы решили эту проблему, рассмотрите возможность редактирования и включения решения в ответ, чтобы вопрос не отображался в разделе «Неотвеченные».   -  person jscs    schedule 17.03.2011


Ответы (1)


Самостоятельное решение этого ответа по рекомендации Джоша Касвелла.


Я спросил об этом на встрече CocoaHeads. Мне предложили взглянуть на hitTest от NSView. Итак, в обоих моих пользовательских представлениях я переопределяю самую популярную функцию NSView следующим образом:

- (NSView*) hitTest:(NSPoint)aPoint {
    static int depth = 1;
    NSLog([NSString stringWithFormat:@"%%%dd ENTER %%@ - hitTest", depth], 
          depth, [[self class] description]);
    depth++;
    NSView *hitView = [super hitTest:aPoint];
    depth--;
    NSLog([NSString stringWithFormat:@"%%%dd EXIT %%@ - hitTest: %%@", depth], 
          depth, [[self class] description], [[hitView class] description]);
    return hitView;
}

Ниже приведен вывод:

MyCustomView — это подвид contentView.
MyOpaqueCustomView (OCV) — это подвид contentView.

1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
MyCustomView - Dirty Rect: {{49, 189}, {127, 28} //!!Focus Ring Around Text Field
OCV - Dirty Rect: : {{49, 189}, {127, 28}}
testTextField isOpaque? Yes
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 ENTER MyCustomView - hitTest
1 EXIT MyCustomView - hitTest: MyCustomView
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}} //!!EVERY BLINK
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}

MyCustomView — это подвид contentView.
MyOpaqueCustomView (OCV) — это подвид MyCustomView.

1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 EXIT MyCustomView - hitTest: NSTextField
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 EXIT MyCustomView - hitTest: NSTextField
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 EXIT MyCustomView - hitTest: NSTextView
OCV - Dirty Rect: : {{49, 189}, {127, 28}} //!!FOCUS RING
testTextField isOpaque? Yes
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 EXIT MyCustomView - hitTest: NSTextView
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 EXIT MyCustomView - hitTest: NSTextView
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 EXIT MyCustomView - hitTest: NSTextField
//!!BLINKING HERE - But no dirtyRects.

Таким образом, похоже, что ответ на hitTest определяет, какие представления будут перерисованы.

person Tobias    schedule 18.03.2011