#objective-c #macos #cocoa #graphics
#цель-c #macos #какао #графика
Вопрос:
У меня есть пользовательский вид ( NSView
подкласс), и я хотел бы сохранить некоторые данные на основе размеров (ширина / высота) представления при создании экземпляра представления, т. Е. До drawRect
вызова.
Я ожидал бы, что смогу использовать initWithFrame
и брать границы из переданного NSRect
, но если я проверю данные в отладчике, я просто получу NSRect
экземпляр с. (x=0, y=0), (width=0, height=0)
Предположительно, он еще не инициализирован?
Более загадочным является то, что если я регистрирую ширину фрейма на консоли, я получаю значение дважды:
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGFloat width = frame.size.width;
NSLog(@"width: %f", width);
}
}
Этот код регистрирует:
21/10/2011 09:40:55.733 Test App: width: 480.000000
21/10/2011 09:40:55.818 Test App: width: 0.000000
Это как если бы initWithFrame выполняется в двух отдельных потоках, и у нас есть какое-то условие гонки. Каков правильный способ получить ширину кадра при инициализации представления?
ОБНОВЛЕНИЕ [РЕШЕНО]: теперь эта проблема решена. Оказывается, у меня было два экземпляра моего NSView
подкласса в Interface Builder. Один был нарисован в Custom View
виде буквы «а», а другой — Object
в виде буквы «а» на боковой панели. Я не понимал, что добавление объекта на боковую панель приводит к его созданию во время выполнения. Удалил объект, и теперь мой код работает.
Комментарии:
1. Если бы я пытался это отладить, я бы посмотрел, вызывал ли я initWithFram сам и автоматически получал его с помощью отношения InterfaceBuilder?
2. Он вызывается автоматически, поскольку у меня есть a
Custom View
в IB, а егоClass
поле установлено для моегоTestCanvas
класса (какие подклассыNSView
). Я не создаю экземпляр «вручную»TestCanvas
нигде в своем коде. Возможно ли, что он вызывается один раз приNSWindow
создании и снова при созданииCustom View
внутри него или наоборот?3. Возможно, но время, которое вы регистрируете, предполагает, что он вызывается с размером 0 после правильного размера. Просто поставьте условие, проверяя, равен ли размер 0. Если это не так, обрабатывайте данные по своему усмотрению?
4. Интересно, что они не всегда происходят в таком порядке. Иногда я получаю 0, а затем 480, что придает вес моей теории условий гонки. Предложенное вами условие заставит меня работать (спасибо!), Но это хак, и я бы в конечном итоге хотел понять, что происходит. Я мог бы попробовать создать минимальный рабочий пример с нуля и посмотреть, смогу ли я воспроизвести проблему.
5. Я нашел причину проблемы, см. Обновление выше.
Ответ №1:
Кадр, переданный в initWithFrame, является кадром, используемым представлением, вы уверены, что не создаете два представления или не вызываете это дважды?
Комментарии:
1. У меня есть
NSWindow
внутри .xib, и внутри него естьCustom View
Class
поле, для которого установлено значениеTestCanvas
. Внутри TestCanvas подклассыNSView
и обеспечивает реализациюinitWithFrame
. Все работает так, как ожидалось (я могу рисовать в представлении сdrawRect
помощью , за исключением того, чтоinitWithFrame
вызывается дважды. Вполне возможно, что я получаю два экземпляра TestCanvas, но я не могу сказать почему.