Фиксированный стиль с проблемами сгруппированной таблицы

#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 or NSMutableDictionary , у которого нет 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. Анна Каренина, спасибо, что нашли время рассказать об этом подробнее. Я всю неделю бился головой об это и документы. С благодарностью (и теперь узнал.)