NSString drawInRect:withAttributes: вызывает «неопознанный селектор, отправленный экземпляру»

Я получил что-то действительно странное: метод вызывает unrecognized selector sent to instance, но не NSLog() вообще ничего.

Я создал собственный подкласс NSControl, в котором я пытаюсь нарисовать свои пользовательские ячейки следующим образом:

- (void)drawRect:(NSRect)dirtyRect {
    NSLog(@"DrawRect entered!");
    [[NSColor grayColor] set];
    [NSBezierPath fillRect:[self bounds]];

    unsigned int i, count = [cells count];
    NSRect cellRect = NSMakeRect(0, 0, ([self bounds]).size.width, cellHeight);
    for (i = 0; i < count; i++) {
        NSLog(@"Drawing cell %d at: %@", i, NSStringFromRect(cellRect));
        MKMenuCell *cell = [cells objectAtIndex:i];
        [cell drawWithFrame:cellRect inView:self];
        cellRect.origin.y += cellHeight;
    }
}

И -[MKMenuCell drawWithFrame:inView:]:

- (void)drawWithFrame:(NSRect)bounds inView:(NSView *)controlView {
    NSLog(@"-drawWithFrame:inView:");
    NSMutableDictionary *strAttribs = [[NSMutableDictionary alloc] init];
    [strAttribs setObject:[NSColor blackColor] forKey:NSFontAttributeName];
    [name drawInRect:bounds withAttributes:strAttribs]; // "unrecognized selector sent ..." is caused by this method call.
}

Выход:

2013-03-11 18:46:54.823 MacOverflow[738:a0f] DrawRect entered!
2013-03-11 18:46:54.826 MacOverflow[738:a0f] Drawing cell 0 at: {{0, 0}, {176, 30}}
2013-03-11 18:46:54.826 MacOverflow[738:a0f] -drawWithFrame:inView:
2013-03-11 18:46:54.827 MacOverflow[738:a0f] Drawing cell 1 at: {{0, 30}, {176, 30}}
2013-03-11 18:46:54.828 MacOverflow[738:a0f] -drawWithFrame:inView:
2013-03-11 18:46:54.828 MacOverflow[738:a0f] -[NSCachedWhiteColor screenFontWithRenderingMode:]: unrecognized selector sent to instance 0x100512920
2013-03-11 18:46:54.829 MacOverflow[738:a0f] An uncaught exception was raised
2013-03-11 18:46:54.831 MacOverflow[738:a0f] -[NSCachedWhiteColor screenFontWithRenderingMode:]: unrecognized selector sent to instance 0x100512920
2013-03-11 18:46:54.834 MacOverflow[738:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCachedWhiteColor screenFontWithRenderingMode:]: unrecognized selector sent to instance 0x100512920'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00007fff88c26784 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x00007fff858ddf03 objc_exception_throw + 45
    2   CoreFoundation                      0x00007fff88c80110 +[NSObject(NSObject) doesNotRecognizeSelector:] + 0
    3   CoreFoundation                      0x00007fff88bf88ef ___forwarding___ + 751
    4   CoreFoundation                      0x00007fff88bf4a38 _CF_forwarding_prep_0 + 232
    5   AppKit                              0x00007fff89afcfae +[NSStringDrawingTextStorage _fastDrawString:attributes:length:inRect:graphicsContext:baselineRendering:usesFontLeading:usesScreenFont:typesetterBehavior:paragraphStyle:lineBreakMode:boundingRect:padding:scrollable:] + 402
    6   AppKit                              0x00007fff896db539 _NSStringDrawingCore + 1588
    7   MacOverflow                         0x00000001000159b7 -[MKMenuCell drawWithFrame:inView:] + 229
    8   MacOverflow                         0x0000000100015f1e -[MKMenuControl drawRect:] + 595
    9   AppKit                              0x00007fff896d6cc5 -[NSView _drawRect:clip:] + 3390
    10  AppKit                              0x00007fff896d5938 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1325
    11  AppKit                              0x00007fff896d5ca2 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2199
    12  AppKit                              0x00007fff896d5ca2 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2199
    13  AppKit                              0x00007fff896d5ca2 -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2199
    14  AppKit                              0x00007fff896d400a -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 767
    15  AppKit                              0x00007fff896d3b2c -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 254
    16  AppKit                              0x00007fff896d03de -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 2683
    17  AppKit                              0x00007fff89649c0e -[NSView displayIfNeeded] + 969
    18  AppKit                              0x00007fff89611c3b -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 1050
    19  AppKit                              0x00007fff896117d2 -[NSWindow orderWindow:relativeTo:] + 94
    20  AppKit                              0x00007fff895dd974 -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] + 1726
    21  AppKiProgram received signal:  “SIGABRT”.
t                              0x00007fff895dba91 loadNib + 226
    22  AppKit                              0x00007fff895dafa1 +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] + 248
    23  AppKit                              0x00007fff895dadd9 +[NSBundle(NSNibLoading) loadNibNamed:owner:] + 326
    24  AppKit                              0x00007fff895d835b NSApplicationMain + 279
    25  MacOverflow                         0x0000000100000ef9 main + 33
    26  MacOverflow                         0x0000000100000ed0 start + 52
    27  ???                                 0x0000000000000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'

Как видите, зовут drawWithFrame:inView: MKMenuCell. но вывод его оператора NSLog() не отображается. Что здесь происходит? Как это решить?

EDIT: Теперь я понимаю, глядя на вывод GDB, что в первый раз все идет не так. Это делает его еще более странным.


person 11684    schedule 11.03.2013    source источник
comment
([self bounds]).size.width - Аргх, а почему бы и нет self.bounds.size.width?   -  person    schedule 11.03.2013
comment
@ H2CO3 Извините, я создал прототип этого кода на машине с Objective-C 1 ... Но я думаю, что уже нашел проблему (еще не проверял): я установил цвет для ключа NSFontAttributeName. NSString ищет значение для NSFontAttributeName, думает, что это NSFont (но это NSColor). Отсюда и непризнанный селектор. Вывод ошибки блокирует поток stdout для моего оператора NSLog(). Но это все не проверено. Я оставлю вопрос здесь, чтобы другие люди могли увидеть код; у него может быть несколько проблем.   -  person 11684    schedule 11.03.2013


Ответы (1)


Отправляемый неверный селектор, screenFontWithRenderingMode, является методом NSFont. Держу пари, что вам не следует устанавливать цвет для значения ключа NSFontAttributeName. Вы, вероятно, должны дать ему шрифт.

person Tom Hamming    schedule 11.03.2013
comment
Я уже заметил это (см. мой комментарий к вопросу), но оставил вопрос здесь, потому что не был уверен, что это единственная проблема. - person 11684; 11.03.2013
comment
@ 11684: Дело не в том, что проблема «блокирует поток stdout для моего оператора NSLog()»; дело в том, что он вызывает исключение, которое завершает выполнение вашего кода и возвращает ваше приложение обратно в самый внутренний цикл выполнения (или, в некоторых случаях, полностью его завершает). Ваш внутренний метод не продвинулся дальше вашей попытки drawInRect:withAttributes:; ваш внешний метод вошел в цикл только один раз. Исправление исключения (не помещая цвет там, где ожидается шрифт) исправит цикл. - person Peter Hosey; 12.03.2013
comment
Ну, вы ошибаетесь (это звучит грубо, но это не так. Я не являюсь носителем английского языка). Цикл запускается дважды (поскольку первое значение в массиве равно нулю, еще одна проблема с кодом), а оператор NSLog находится перед строкой, выдающей ошибку. Я думаю, что stdout буферизует это, а затем stderr вставляется. После этого приложение завершает работу, не очищая буфер stdout. - person 11684; 12.03.2013
comment
@ 11684: Вы правы, цикл выполняется дважды, а не один раз; Я этого не видел. Под «первым значением в массиве» вы должны понимать имя первой ячейки, потому что сама первая ячейка не может быть nil — массивы не могут содержать nil. Принимая это во внимание, мое объяснение остается в силе: как только вы отправите drawInRect:withAttributes: в фактическую строку, которая попытается использовать ваши недопустимые атрибуты, что вы в настоящее время делаете во второй ячейке, строка выдаст исключение, которое выйдет из цикла. — на самом деле, полностью из вашего кода — в этот момент. - person Peter Hosey; 12.03.2013
comment
Эй, журнал, который я распечатал, содержит больше журналов, чем первый. Извините, я основывал свои комментарии на другом журнале (я запускал этот код сотни раз, потому что не понимал, что пошло не так), и этот журнал оказался немного другим... Мои извинения! - person 11684; 12.03.2013