Передача NSMutableArray в функцию - PullRequest
3 голосов
/ 10 июня 2009

У меня проблема с Какао, я вызываю функцию и передаю ей массив:

Некоторые, где я вызываю функцию:

[self processLabels:labels];

И функция выглядит следующим образом:

- (void)processLabels:(NSMutableArray*)labs{
    labs = [[NSMutableArray alloc] init];
    [labs addObject:@"Random"];
....
}

При отладке я замечаю, что при добавлении в лаборатории новые объекты не добавляются в ярлыки. Это потому, что я заново инициализирую лаборатории? как я мог тогда повторно инициализировать метки внутри функции?

Я пытался использовать byref, но не получилось, любая помощь приветствуется .. спасибо

Ответы [ 5 ]

3 голосов
/ 10 июня 2009

'labs' должны быть инициализированы до того, как вы передадите его в processLabels, а затем не должны быть повторно инициализированы.

Если по какой-либо причине вы не можете заранее инициализировать массив и хотите, чтобы processLabels его создал, вам нужно передать указатель на указатель:

[self processLabels:&labels];

и метод изменится на:

- (void)processLabels:(NSMutableArray**)labs{
    *labs = [[NSMutableArray alloc] init];
    [*labs addObject:@"Random"];
....
}
2 голосов
/ 10 июня 2009

обычно говорят, что предпочтительно не передавать изменяемые коллекции, а предоставлять методы, которые над ними работают ...

фактически, в ответ на ваш код, мне даже интересно, какова цель передачи массива 'labs' в функцию, когда на самом деле вы просто перезаписываете его (и создаете утечку памяти в процессе). зачем это?

1 голос
/ 10 июня 2009

Воля верна, как в отношении исправления существующего метода, так и в отношении того, что это плохая идея. Сохранение обратного параметра-ссылки, безусловно, допустимо и часто используется в простых программах на Си, но в этом случае добавляет ненужную сложность. В Objective-C предпочтительная идиома состоит в том, чтобы сначала возвращать объекты, используя возвращаемое значение, и сохранять их обратно в указатель, только если возвращаемое значение уже используется для возврата чего-то еще. Это не только облегчит чтение и запись метода, но и соответствует стандартным идиомам, которые обычно используются в других языках (таких как Java и C #). Это становится совершенно очевидным, если перезаписать указатель массива, присвоив ему потенциальную ошибку, которая с большей вероятностью будет обнаружена такими инструментами, как Clang Static Analyzer .

В соответствующей заметке вам, вероятно, следует также рассмотреть возможность присвоения имен методам и параметрам. (Я понимаю, что это, вероятно, несколько надуманный пример.) Если вы обрабатываете «метки», и они приходят из какого-то другого источника, кроме создаваемого изменяемого массива, я бы не назвал локальную переменную «labs» или « метки "- используйте более описательное имя. Имена методов, которые являются менее расплывчатыми в отношении того, что они делают, могут значительно улучшить читаемость кода. В Objective-C предпочтительными являются длинные описательные имена методов. Поскольку XCode выполняет завершение кода, а имена методов менее неоднозначны, конечный результат обычно меньше ввода.

1 голос
/ 10 июня 2009

Оператор labs = [[NSMutableArray alloc] init]; заставляет labs указывать на новый массив в области действия метода. Это не делает указатель вызывающей стороны указывать на новый массив.

Если вы хотите изменить указатель вызывающего абонента, сделайте что-то вроде этого:

// The caller
NSMutableArray *labels;         // Don't initialize *labels.
[self processLabels:&labels];

...

- (void)processLabels:(NSMutableArray**)labs{
    *labs = [[NSMutableArray alloc] init];
    [*labs addObject:@"Random"];
    ...
}

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

Если вы хотите, чтобы вызывающая сторона владела массивом, вы можете написать processLabels: следующим образом:

- (void)processLabels:(NSMutableArray*)labs{
    [labs removeAllObjects];
    [labs addObject:@"Random"];
    ...
}

Или, если processLabels: просто возвращает коллекцию меток:

- (NSMutableArray*)processLabels {
    NSMutableArray* labs = [[[NSMutableArray alloc] init] autorelease];
    [labs addObject:@"Random"];
    ...
    return labs;
}

Если вы хотите, чтобы вызывающая сторона отвечала за освобождение массива, удалите авторелиз. В этом случае соглашение предписывает, чтобы имя метода начиналось с alloc или new или содержало слово copy.

1 голос
/ 10 июня 2009

Вам нужно передать изменяемый массив, чтобы иметь возможность его изменить (это определение Mutable) - чтобы превратить NSArray в изменяемый массив, используйте:

NSMutableArray *writableArray = [NSMutableArray arrayWithArray:oldArray];

или если вы просто хотите создать пустой изменяемый массив:

NSMutableArray *writableArray = [NSMutableArray array];

Тогда передайте это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...