NSMutableArray и pointer: операция над указателем - это операция с исходным массивом (?) - PullRequest
0 голосов
/ 03 июня 2011

Это довольно долгий путь, чтобы задать простой вопрос, но, учитывая, насколько запутанные указатели в Objective-C для некоторых, может быть, проверка того, что здесь происходит, поможет другим, а также мне.

Итак, в двух словах, у меня есть UITableView, с помощью которого вы можете включить редактирование и удалить строку.Я хочу удалить строку из табличного представления и источник (и) данных.Исходный источник данных находится в классе модели, но у меня есть указатель / свойство, содержащее данные в моем локальном контроллере табличного представления.Когда я удаляю строку из табличного представления путем редактирования, кажется, что он работает и удаляет данные ... но я не понимаю, почему.Я думаю, это из-за моего фундаментального неправильного понимания указателей.

В моем классе модели с NSMutableArray:

@property (nonatomic,retain) NSMutableArray *allAlarms;
// ... plist gets read and serialized to an array ...
allAlarms = [NSMutableArray arrayWithArray:[plistValues objectForKey:@"Alarms"]];

В классе UITableViewController я извлекаю этот изменяемый массив через свойство во время viewWillAppear:

@property (nonatomic, retain) NSMutableArray *alarms;

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // retrieve values from data controller
    self.alarms = [dataController returnAllAlarms];
    [self.tableView reloadData];
}

Когда выполняется метод делегата для редактирования, я делаю это, и он работает ...

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
    // Delete the row from the local data source
    [self.alarms removeObjectAtIndex:indexPath.row]; 
    // The above line appears to delete it in the local pointer as well as in the original property in the model class
    // so I just have to tell the data controller to save plist for when it's read back in via viewWillAppear
    [dataController writePlist];
    // Delete the row from the table view
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}   

}

Почему происходит то, что происходитв моем tableView: commitEditingStyle: forRowAtIndexPath в конечном итоге работать?Удаление элемента из указателя на NSMutableArray в моем локальном классе также удаляет его в исходном указателе в удаленном классе, потому что первый является указателем на последний?

Мне нужно понять, потому что есть другие операцииЯ буду выполнять этот локальный указатель и хочу убедиться, что я не буду лишним, чтобы выполнять его на удаленном свойстве и т. Д. Есть ли что-то в том, что я делаю, неинтуитивно и избыточно, или это сделает большесмысл, как я продолжаю изучать Objective-C и больше использовать указатели?

1 Ответ

1 голос
/ 03 июня 2011

Да, похоже, вы не совсем понимаете, как работают указатели.Вместо того, чтобы пытаться объяснить все это сам, я укажу вам на эту тщательную главу об указателях .

Одна вещь, которую нужно отметить, состоит в том, что в Objective-C вы никогда не размещаете объектыстек 1 .Объекты всегда размещаются в куче, и вам возвращается указатель.(как malloc().) Вот почему всегда есть звездочка (*) в типе объекта 2 .И ваша модель, и контроллер имеют указатели на один и тот же базовый массив.self.alarms = [dataController allAlarms] не копирует массив, он копирует указатель 3 .

Когда вы вызываете removeObjectAtIndex:, он ничего не меняет в указателе- указатель - это просто число - он разыменовывает указатель и работает с базовым объектом в памяти.

1. С одним незначительным исключением Blocks.
2. За исключением id, то есть typedef 'ed.
3. Если вы do хотите скопировать массив, используйте(copy) атрибут свойства, а не (retain).

...