#ios #uitableview
#iOS #uitableview
Вопрос:
Мне трудно разобраться в этом. Я загружаю массив NSMutable из файла plist и заполняю сгруппированную таблицу данными. Таблица состоит из 3 разделов, раздел 0 недоступен для редактирования, но два других доступны — у меня это ограничение работает. Моя проблема заключается в том, что пользователь решает удалить строку в двух редактируемых разделах. Я полагаю, это потому, что у меня есть два ключа для каждой записи — один для ее имени, а другой для ее URL.
Вот пример моего списка. ключ заголовка используется для названий разделов. Затем есть ключ для ‘Rows’ — это текст, который отображается в каждой ячейке, а затем ‘url’, который при выборе строки загружает URL в webview. Я знаю, что хочу захватить раздел и строку, которые выбирает пользователь, а затем удалить как «Строку», так и «URL» для этого индекса. Любая помощь была бы высоко оценена.
Вот мой список:
<array>
<dict>
<key>Title</key>
<string>Query</string>
<key>Rows</key>
<array>
<string>Non-editable String 1</string>
<string>Non-editable String 2</string>
<string>Non-editable String 3</string>
<string>Non-editable String 4</string>
</array>
</dict>
<dict>
<key>Title</key>
<string>Resources</string>
<key>Rows</key>
<array>
<string>Website Name 1</string>
<string>Website Name 2</string>
<string>Website Name 3</string>
<string>Website Name 4</string>
<string>Website Name 5</string>
</array>
<key>url</key>
<array>
<string>http://website1.com</string>
<string>http://website2.com</string>
<string>http://website3.com</string>
<string>http://website4.com</string>
<string>http://website5.com</string>
</array>
</dict>
<dict>
<key>Title</key>
<string>Monitoring</string>
<key>Rows</key>
<array>
<string>Website Name 6</string>
<string>Website Name 7</string>
<string>Website Name 8</string>
</array>
<key>url</key>
<array>
<string>http://website6.com</string>
<string>http://website7.com</string>
<string>http://website8.com</string>
</array>
</dict>
Это ограничивает редактирование двумя последними разделами
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0)
return UITableViewCellEditingStyleNone;
else
return UITableViewCellEditingStyleDelete;
}
Это (нерабочий код) для фиксации удаления (tableData — это имя моего изменяемого массива). Мое приложение бомбит на:
[[self.tableData objectAtIndex:indexPath.section] removeObjectAtIndex:indexPath.row];
Но угадывание deleteRowsAtIndexPaths тоже неверно.
Код:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.tableView beginUpdates];
[[self.tableData objectAtIndex:indexPath.section] removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath.row] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
[self.tableView reloadData];
}
—ОБНОВИТЬ—
Если я сделаю это таким образом и установлю для section и row значение NSUInteger, при регистрации будут зарегистрированы правильные section и row. Тем не менее, я терплю крах в
[[self.tableData objectAtIndex:section] removeObjectAtIndex:row];
В моей консоли я получаю эту ошибку: Завершение работы приложения из-за неперехваченного исключения ‘NSInvalidArgumentException’, причина: ‘-[__NSCFDictionary removeObjectAtIndex:]: нераспознанный селектор, отправленный экземпляру 0x4b43b20’
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSUInteger row = [indexPath row];
NSLog(@"NSUInteger Row: %d", row);
NSUInteger section = [indexPath section];
NSLog(@"NSUInteger Section: %d", section);
[self.tableView beginUpdates];
[[self.tableData objectAtIndex:section] removeObjectAtIndex:row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:row inSection:section]] withRowAnimation:UITableViewRowAnimationFade];
Комментарии:
1. Неверный параметр deleteRowsAtIndexPaths (необходимо передать массив NSIndexPaths, а не целых чисел), но какую ошибку вы получаете, когда происходит сбой в строке removeObjectAtIndex?
2. Просто ‘terminate вызывается после создания экземпляра ‘NSException»
3. Попробуйте разбить эту строку на два оператора. Получите объект в indexPath.section и запишите его в журнал. В этом объекте зарегистрируйте объект в indexPath.row . Пройдитесь по коду в отладчике, чтобы быть уверенным, какая строка вылетает и, возможно, почему.
4. В приведенной выше ошибке нераспознанный селектор отправлен экземпляру 0x4b43b20′, этот адрес памяти относится к (правильному) разделу, который был выбран. Итак, мне кажется, что у него проблема со строкой?
5. Эта ошибка означает, что
[self.tableData objectAtIndex:section]
этоNSDictionary
orNSMutableDictionary
, у которого нетremoveObjectAtIndex:
метода (это неNSMutableArray
).
Ответ №1:
Для вашего plist tableData
переменная — это an NSMutableArray
, которая содержит 3 объекта, каждый из которых является NSMutableDictionary
(несмотря на то, что в документах указано, что это должен быть NSDictionary-неизменяемый).
Второй и третий словари содержат три ключа: заголовок, строки и URL
Значения строк и ключей URL являются NSMutableArrays
(опять же, несмотря на то, что в документах говорится, что они должны быть NSArrays—неизменяемыми).
В любом случае, после прочтения plist объекты, которые вы хотите изменить, должны так или иначе быть изменяемыми либо по умолчанию, либо при вашем явном вызове mutableCopy
.
В commitEditingStyle
методе вам нужно вызывать removeObjectAtIndex
массивы, а не словарь разделов. Итак, сначала получите ссылку на строки и массивы URL (вы должны делать что-то подобное в cellForRowAtIndexPath
для отображения значений).
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSMutableDictionary *sectionDict = [tableData objectAtIndex:indexPath.section];
NSMutableArray *sectionRows = [sectionDict objectForKey:@"Rows"];
NSMutableArray *sectionUrls = [sectionDict objectForKey:@"url"];
[sectionRows removeObjectAtIndex:indexPath.row];
[sectionUrls removeObjectAtIndex:indexPath.row];
//don't need beginUpdates (we're making only one delete call)
//tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
//don't need endUpdates (since we're not doing beginUpdates)
//[tableView endUpdates];
//don't need reloadData since we're calling deleteRowsAtIndexPaths
//(or call reloadData instead of deleteRowsAtIndexPaths)
//[tableView reloadData];
}
}
Комментарии:
1. Анна Каренина, спасибо, что нашли время рассказать об этом подробнее. Я всю неделю бился головой об это и документы. С благодарностью (и теперь узнал.)