Динамический массив в стиле c. Когда использовать retain, что выпустить и когда это сделать - PullRequest
1 голос
/ 08 апреля 2011

В свете моего последнего вопроса я решил начать с простого класса, содержащего данные двумерного массива.

Интерфейс:

@interface DynamicTable
NSString ***data;
NSInteger _cols;
NSInteger _rows;
@end

Initializer:

-(id)initWithRows:(NSInteger)rows withCols:(NSInteger)cols {
    if (self = [super init]) {

        _rows = rows;
        _cols = cols;

        data = (NSString ***)malloc(_rows * sizeof(NSString **));
        for (int i = 0; i < _rows; ++i) {
            data[i] = (NSString **)malloc(_cols * sizeof(NSString *));
            for (int j = 0; j < _cols; ++j) {
                NSString *cell = [[NSString alloc] initWithFormat:@"%d",(i + j)];
                data[i][j] = cell;
            }
        }
    }
    return self;
}

Мы сохраняем или нет?
В данный момент я провожу большую дискуссию со стажером (который раньше разрабатывал для iPhone, где я еще не занимался), не задал ли вопрос data [i] [j] = cell; не должно быть data [i] [j] = [сохранение ячейки]; .
Вторая версия пришла из другого примера здесь, на SO. С того же вопроса я скопировал процедуру dealloc.

Мы отпускаем по заданию?
Следующий бит кода отвечает за установку нового значения в данной ячейке. Опять же, возникает вопрос, стоит ли освобождать первоначальное значение (я уже понял, что это все по ссылке).

-(void)setValue:(NSString *)value atRow:(NSInteger)row atCol:(NSInteger)col {
    //NSString *cell = data[row][col];
    data[row][col] = value;
    //[cell release];
}

Как видите, я закомментировал бит, который должен освобождать исходное значение.

Весь процесс управления памятью в iPhone выглядит довольно ужасно. Я много читал об этом на сайте Apple и других об этом, но это многое нужно принять сразу. Маленькие примеры с ясным объяснением обычно работают лучше всего для меня. LOL

Вернуться к моему вопросу:
С моей точки зрения (не уверен, что я прав) я должен освободить исходное значение, которое было помещено в данную ячейку. Кто-нибудь может подтвердить, что я на правильном пути?

PS Я пытался использовать инструмент Run with Performance Tool -> Leaks ... Но и мое отсутствие знаний об iPhone слишком сильно сдерживает меня.

Ответы [ 2 ]

4 голосов
/ 08 апреля 2011

Я согласен с Дэвидом, придерживайтесь Objective-C , но я отвечу на ваш первоначальный вопрос, так как это может помочь вам перейти в Objective-C.

Первый пример сделан правильно. Следующее возвращает сохраненную строку, потому что вы вызвали alloc / init.

NSString *cell = [[NSString alloc] initWithFormat:@"%d",(i + j)];
data[i][j] = cell;

Ваш dealloc вызов будет выглядеть примерно так

-(void)dealloc
{
    for(int i = 0; i < _rows; ++i)
    {
        for(int j = 0; j < _cols; ++j)
        {
            [data[i][j] release];
        }
        free(data[i]);
    }
    free(data);

    [super dealloc];
}

Теперь для вашего второго примера вам нужно сохранить значение, но также освободить предыдущее значение.

-(void)setValue:(NSString *)value atRow:(NSInteger)row atCol:(NSInteger)col {
    [value retain]; //retain in case value is the same
    [data[row][col] release];
    data[row][col] = value;
}

Я не верю, что Управление памятью ужасно в Objective-C, и на самом деле есть только несколько основных правил, которым нужно следовать за редкими исключениями (-[NSAutoreleasePool drain] приходит на ум).

2 голосов
/ 08 апреля 2011

Вы пытаетесь написать некоторый код c в среде target-c.Если бы я был тобой, я бы придерживался target-c и использовал c редко.Вот как это будет выглядеть в target-c.

@interface DynamicTable
NSMutableArray *data;
NSInteger _cols;
NSInteger _rows;
@end

-(id)initWithRows:(NSInteger)rows withCols:(NSInteger)cols 
{
    if (self = [super init]) 
    {
        _rows = rows;
        _cols = cols;

        data = [[NSMutableArray alloc] init]; //Release in dealloc method

        for (int i = 0; i < _rows; ++i) 
        {
            NSMutableArray *cells = [NSMutableArray array]; //Auto released

            for (int j = 0; j < _cols; ++j) 
            {
                NSString *cell = [[NSString alloc] initWithFormat:@"%d",(i + j)];
                [cells addObject:cell]; //Auto retains
                [cell release]; //Release
            }

            [data addObject:cells];
        }
    }
    return self;
}

А вот что вы бы сделали в вашем аксессоре.

-(void)setValue:(NSString *)value atRow:(NSInteger)row atCol:(NSInteger)col 
{
    [[data objectAtIndex:row] insertObject:value atIndex:col]; //Auto retained
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...