#objective-c #cocoa #xcode4 #nscell
#objective-c #cocoa #xcode4 #nscell
Вопрос:
У меня есть NSTableView
в моем главном окне файл NIB, который использует динамически созданный источник данных — то есть массив словарей создается динамически при необходимости — в одном из моих классов. Таким образом, он не связан никакими контроллерами в IB.
В tableview есть 2 столбца, которые имеют подкласс DataCell set.
NSTableColumn *detailsColumn = [[tableView tableColumns] objectAtIndex:0];
imageColumnCell *fileDetails = [[[imageColumnCell alloc] init] autorelease];
[detailsColumn setDataCell:fileDetails];
[fileDetails setNumberOfUploads:numberOfFiles];
NSTableColumn *cancelColumn = [[tableView tableColumns] objectAtIndex:1];
cancelButtonCell *cancelCell = [[[cancelButtonCell alloc] init] autorelease];
[cancelColumn setDataCell:cancelCell];
В <NSTableViewDataSource>
файле numberOfRowsInTableView:
задано правильное количество динамически создаваемого массива, и GDB правильно регистрирует его при построении таблицы.
Теперь возникает проблема. Из гипотетических соображений предположим, что количество массивов для источника данных равно 1
В обоих подклассах NSCell
я перезаписал drawInteriorWithFrame:inView:
метод для обработки всего рисунка (изображений, текста, кнопок и т.д.) Внутри ячеек таблицы. NSDictionary
Для каждого столбца содержит строку (столбец 1) и ссылку на объект для (столбец 2).
Основываясь на примере 1 объекта в источнике данных, если бы в drawInteriorWithFrame:inView:
я должен был написать следующее (в столбце 2):
NSLog(@"drawInteriorWithFrame: in cancelButtonCell - %@", [self objectValue]);
Ожидаемый результат (без щелчка по таблице, прокрутки и т.д.) В GDB должен содержать 1 экземпляр этого:
[0000:000] drawInteriorWithFrame: in cancelButtonCell - <object: 0x123456>
И если бы я щелкнул или прокрутил таблицу, то она должна была бы возвращать одинаковые значения для каждого действия в tableview. Однако при первой загрузке я получаю что-то вроде этого:
[0000:000] drawInteriorWithFrame: in cancelButtonCell - <object: 0x123af06>
[0000:000] drawInteriorWithFrame: in cancelButtonCell - <object: 0x12b3236>
Если есть 2 результата, то я получаю 3 элемента журнала, а в других случаях 4. В большинстве случаев метод вызывается на 1 раз больше, чем следовало бы.
Вторая проблема, которая возникла совсем недавно, заключается в том, что если вы обратите внимание на идентификатор объекта выше, вы увидите, что они разные. Если я добавлю 1 элемент к источнику данных, когда я вызываю [self objectValue]
, если таблица перерисовывается, идентификатор объекта должен быть таким же, поскольку это ссылка — ie. объект уже -alloc
создан в предыдущем классе, и я просто отправляю ссылку на объект.
Я надеюсь, что это имеет смысл, но я весь последний день ломал голову, пытаясь понять, не дублирую ли я что-нибудь где-нибудь по ошибке, и не могу найти никаких проблем. Если вам нужно больше кода, дайте мне знать. Я тоже пробовал Google и получил только ссылку на это:
http://forum.soft32.com/mac/NSPopUpButtonCell-view-refresh-ftopict46690.html
Заранее спасибо.
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSString *columnIdentifier = [tableColumn identifier];
NSDictionary *theDict = [fileSourceArray objectAtIndex:row];
MyAppMethods *appMethods = [MyAppMethods alloc];
if([appMethods getIsComplete:self])
return nil;
if([columnIdentifier isEqualToString:@"fileCancel"]){
if([[theDict objectForKey:columnIdentifier] isKindOfClass:[ASIFormDataRequest class]]){
ASIFormDataRequest *fileUploadRequest = [theDict objectForKey:columnIdentifier];
NSLog(@"in tableView:objectValueForTableColumn:row %@", fileUploadRequest);
return fileUploadRequest;
}
}
return [theDict objectForKey:columnIdentifier];
}
Дополнительный вывод для обсуждения ниже.
Вывод из GDB
** 1 файл, 1 набор NSCell и подкласс ** Здесь запрос остается неизменным — (т. Е. без копирования)
[6619:903] <ASIFormDataRequest: 0x10ca9b0>
[6619:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x10ca9b0>
[6619:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6619:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x10ca9b0>
1 файл, 2 набора NSCell и подкласса
Здесь запрос изменяется в подклассе — (т. Е. без копирования)
[6652:903] <ASIFormDataRequest: 0x103b390>
[6652:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x103b390>
[6652:903] cancelButtonCell.m in - (void)drawInteriorWithFrame:inView: <ASIFormDataRequest: 0x1221b00>
[6652:903] - (id)tableView:objectValueForTableColumn:row: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] imageColumnCell.m in - (void)drawInteriorWithFrame:inView: /Users/byronrode/Desktop/Monika and Lubo/DSC_3379.jpg
[6652:903] - (id)tableView:objectValueForTableColumn:row: <ASIFormDataRequest: 0x103b390>
[6652:903] cancelButtonCell.m in - (void)drawInteriorWithFrame:inView: <ASIFormDataRequest: 0x1227100>
Комментарии:
1. Таблица отображается неправильно, или вы просто обеспокоены очевидным дополнительным вызовом
-drawInteriorWithFrame:
? Кроме того, вы смотрели на представленный объект, прежде чем передать его в ячейку? Как это соотносится с тем, что ячейка говорит о своем значении объекта?2. @josh-caswell — таблица отображается правильно (никаких дополнительных данных). В моем классе, который создает источник данных, фактический объект, словарь и массив, содержащий словарь, содержат один и тот же идентификатор объекта. В источнике данных, в
tableView:objectValueForTableColumn:row:
на объект по-прежнему правильно ссылаются, но в моем подклассе NSCell ссылка изменяется, и все дополнительные вызовы отличаются от исходной ссылки. Я также заметил, чтоtableView:objectValueForTableColumn:row:
вызывается 3 раза для таблицы из 2 столбцов с одной «строкой» в источнике данных.3. При дальнейшем тестировании я обнаружил, что «дополнительные вызовы» связаны с количеством столбцов, что стало более очевидным после того, как я не смотрел на это так долго, так что эта часть имеет смысл. Проблема, похоже, заключается в том, что если я удалю второй подкласс DataCell
cancelColumn
(выше), тогда объект, на который ссылается ссылка, будет правильно идентифицирован. Я обновил вопрос с помощью своего- tableView:objectValueForTableColumn:row:
метода.4. Оба столбца вашей таблицы используют этот же пользовательский класс cell?
5. Нет. Каждый использует отдельный класс cell. Раньше это был один столбец с использованием одной пользовательской ячейки, но была проблема с производительностью при отслеживании мыши, поэтому я разделил его, чтобы отслеживание было связано со столбцом, который нуждался в отслеживании кликов.
Ответ №1:
Я не думаю, что есть о чем беспокоиться, если он отображается правильно. Табличное представление запрашивает в своих столбцах таблицы наличие «фиктивных» ячеек перед завершением их отрисовки; я подозреваю, что это причина дополнительного -draw...
вызова. Кроме того, ячейка копирует свое значение объекта при настройке, так что это, очевидно, придаст ей новый адрес.
В ответ на вашу публикацию сообщений журнала:
Мне не на 100% ясно, когда именно публикуются эти журналы и что они отображают, но это похоже на то, что я ожидал увидеть. В tableView:objectValueForTableColumn:row:
вы печатаете значение, которое у вас есть в вашем словаре, которое совпадает с исходным ASIFormDataRequest
. В drawInteriorWithFrame:inView:
вы печатаете ячейку objectValue
, которая является копией этого оригинала (то есть нового объекта с другим адресом в памяти).
Комментарии:
1. Это имеет смысл, но, несомненно, копирование тогда было бы таким же при использовании одной или двух пользовательских ячеек столбца. За исключением этого случая, адрес изменяется при использовании 2 пользовательских ячеек. Я добавил больше информации к вопросу. Возможно, теперь это будет иметь больше смысла.
2. Мне кажется, что это детали реализации AppKit, которые не влияют на вашу программу. Я все еще говорю «Не беспокойтесь об этом». Для эффективного выполнения своей работы табличный вид, столбцы таблицы и
NSCell
все это делает за кулисами то, чего вы, возможно, не ожидаете.