Вопрос о UITableView и deleteRowsAtIndexPaths - PullRequest
3 голосов
/ 24 сентября 2011

Мой первый вопрос по stackoverflow (<< n00b).Я работаю над своим первым проектом, включающим UITableViews и списки, и у меня возникла проблема. </p>

Список свойств состоит из словаря, содержащего 3 раздела / категории (каждый массив) и несколько записей вкаждый из них.

Списки загружаются просто отлично.Проблема не возникнет, пока я не попытаюсь сделать возможным удаление отдельных записей из списка.

Вот мой код:

- (void)tableView:(UITableView *)tableView commitEditingStyle:    (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) {

    //make array of the objects and remove the selected object from that array.
    NSMutableArray *delArray = [faves objectForKey:[entries objectAtIndex:indexPath.section]];
    [delArray removeObjectAtIndex:indexPath.row];

    //set entries to the value of the array, now sans the removed object.
    self.entries = delArray;
    [delArray release];

    //write the updated entries to the plist file.
    NSArray *rootPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsPath = [rootPath objectAtIndex:0];
    NSString *plistFile = [docsPath stringByAppendingPathComponent:@"Data.plist"];
    [faves writeToFile:plistFile atomically:YES];

    //update the actual tableview. This is where things go awry.
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; //ends up trying to load the sections instead of the entries = wrong number of list items returned = crash!

    //[tableView reloadData]; //works if I only use this line, but the list updates wrong, showing each entry as a section header.
    }
}

Запись удалена из списка корректно, нотаблица не обновляется правильно и вызывает сбой приложения.Я включил код ошибки ниже.

2011-09-23 18:40:19.732 MyApp[10314:b303] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:974
2011-09-23 18:40:19.734 MyApp[10314:b303] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (5) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'

Первое число (5) соответствует количеству записей, которые должны остаться в соответствующей категории, но второе число (3) относится кколичество категорий.Как я уже говорил выше, запись удаляется из списка, а не из таблицы.

Ответы [ 2 ]

2 голосов
/ 04 октября 2011

Учитывая следующие два метода:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [entries count];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
   NSString *key = [entries objectAtIndex:section];
   NSArray *sectionNames = [faves objectForKey:key];
   return [sectionNames count];
} 

Похоже, что "записи" является NSArray имен ключей (NSString), а "faves" является NSDictionary содержимого раздела (NSArrays).

Проблема в том, что вы заменяете свой массив имен ключей (self.entries) на массив содержимого одного раздела. Я расширил ваш код, чтобы сделать логическую ошибку немного более очевидной:

// query for section key name by section index
NSString       * keyName        = [entries objectAtIndex:indexPath.section];

// retrieve array of a section's datasource (array of rows)
NSMutableArray * delArray = [faves objectForKey:keyName];

// remove row from a section's datasource
[delArray removeObjectAtIndex:indexPath.row];

// ERROR: assign an array of rows to array used for section names
self.entries = delArray;

Изменение вашего кода на следующее должно удалить утверждения, сгенерированные UITableView:

(void)tableView:(UITableView *)tableView commitEditingStyle:    (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete) {

//make array of the objects and remove the selected object from that array.
NSMutableArray *delArray = [faves objectForKey:[entries objectAtIndex:indexPath.section]];
[delArray removeObjectAtIndex:indexPath.row];

//write the updated entries to the plist file.
NSArray *rootPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [rootPath objectAtIndex:0];
NSString *plistFile = [docsPath stringByAppendingPathComponent:@"Data.plist"];
[faves writeToFile:plistFile atomically:YES];

//update the actual tableview. This is where things go awry.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; //ends up trying to load the sections instead of the entries = wrong number of list items returned = crash!

//[tableView reloadData]; //works if I only use this line, but the list updates wrong, showing each entry as a section header.
}
0 голосов
/ 20 декабря 2011

Если просмотр таблицы удалить при получении массива из файла plist.Каталог документов - лучший выбор (см. Ниже). Чтобы удалить строку и снова обновить файл plist.В UITableViewCellEditingStyleDelete.

в заголовке

    @property (nonatomic, retain) NSMutableArray *arForTable;

в CellForRowAtindexpath

  cell.textLabel.text=[[ self.arForTable  objectAtIndex:indexPath.row]    
  valueForKey:@"key"];

  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  {

return 1;
   }

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection
      (NSInteger)section
    {

return [self.arForTable count];
    }

в

 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath
   *)indexPath {


   if (editingStyle == UITableViewCellEditingStyleDelete) {

    NSError *error;

    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"data.plist"];
    NSFileManager *fileManager = [NSFileManager defaultManager];

    if (![fileManager fileExistsAtPath:dataPath]) 
 {
    NSString *bundle = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"plist"];

    [fileManager copyItemAtPath:bundle toPath:dataPath error:&error]; 
}

[self.arForTable removeObjectAtIndex:indexPath.row];
[self.arForTable   writeToFile:dataPath atomically:YES];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
   }
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...