Как передать ivar в функцию и установить его, не теряя ссылку на исходный объект

Я передаю ivar (NSMutableArray) в какой-то метод. Я ожидал, что если я изменю объект внутри функции, это будет отражено вне функции, но в этом случае мне нужно установить объект; что-то вроде следующего:

- (void) someMethod:(SMResponseObject *)response onData:(NSMutableArray *)imAnIvar {
    imAnIvar = [response objects];
    //Some other stuff
}

Но я заметил, что ссылка на память imAnIvar внутри функции меняется, когда я ее устанавливаю, и, учитывая это, фактический ivar не меняется. Я понимаю, что проблема в том, что я меняю ссылку на объект внутри метода, поэтому он перестает указывать на ивар, а затем указывает на какое-то другое случайное направление памяти.

Я подумал об одном решении этой проблемы, и оно может заключаться в том, чтобы перед вызовом функции убедиться, что ivar не равен нулю, и сделать что-то вроде этого:

- (void) someMethod:(SMResponseObject *)response onData:(NSMutableArray *)imAnIvar {

    NSMutableArray *data = [response objects];
    [arrayForTableView removeAllObjects];
    for(id element in data){
        [imAnIvar addObject:element];
    }
    //Some other stuff
}

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

if(!_ivar){
  //alloc it
}

Итак, мой вопрос: есть ли способ заставить локальную переменную области видимости указывать на исходную переменную, даже если я ее устанавливаю? если нет, есть ли более чистый способ сделать эту работу?


person clopez    schedule 01.03.2013    source источник
comment
Я заметил, что ссылка на память imAnIvar внутри функции меняется, когда я ее устанавливаю - WAT?   -  person    schedule 01.03.2013
comment
Извините, я изменю его, чтобы сделать его более понятным.   -  person clopez    schedule 01.03.2013
comment
если вы допустили очевидную ошибку, то посмотрите мой ответ и обратите внимание, что в C аргументы функции передаются по значению, а не по ссылке.   -  person    schedule 01.03.2013


Ответы (3)


Вы имеете в виду это?

- (void)setFoo:(SomeClass **)objPtr
{
    *objPtr = someOtherObject;
}

// call it as:

SomeClass *foo = someObject;
NSLog(@"Before: %@", foo);
[self setFoo:&foo];
NSLog(@"After: %@", foo);
person Community    schedule 01.03.2013
comment
Думаю да, попробую! Спасибо - person clopez; 01.03.2013
comment
+1, но это странный/необычный способ делать что-то (за некоторыми редкими исключениями). Обычный способ справиться с этим состоит в том, чтобы -someMethod:... вернуть массив, затем вызывающая программа делает все, что необходимо сделать с возвращенными значениями (например, добавляет их в свой внутренний массив ivar). Если -someMethod:... находится в том же классе, что и imAnIvar, для которого imAnIvar является переменной экземпляра, someMethod:... должна манипулировать ivar(/property) напрямую, без необходимости принимать его в качестве аргумента. - person Andrew Madsen; 01.03.2013
comment
@AndrewMadsen Спасибо. Яп. Я чувствую, что это (еще одна) проблема XY, не так ли? - person ; 01.03.2013
comment
В этом случае ivar не относится к тому же классу, что и someMethod. Вот почему я передаю это как аргумент. На самом деле, решение, предложенное @AndrewMadsen для возврата значения, является лучшим для моего случая, и я думаю, что он предложил это благодаря дополнительному контексту моей проблемы XY. - person clopez; 01.03.2013

Почему бы не использовать геттер для массива, чтобы вам не нужно было проверять, является ли массив нулевым при его использовании?

-(NSMutableArray *)iAmAnIvar {
   if(_iAmAnIvar == nil) {
     _iAmAnIvar = [NSMutableArray array];
   }
   return _iAmAnIvar;
 }

И когда вам нужно установить значение массива, как вы упомянули в своем вопросе, вы можете использовать

[self.iAmAnIvar removeAllObjects];
[self.iAmAnIvar addObject:someObj];
person Shashank    schedule 01.03.2013

Я считаю, что вы можете использовать функцию - (id)copy; NSObject

поэтому ваш код может выглядеть так:

 - (void)someFunction:(NSString *)someArg
 {
     NSString *str = [someArg copy];
 }
person Don    schedule 01.03.2013
comment
Проблема в том, что некоторые объекты вообще не копируются (NSObject), а некоторые не делают глубоких копий. - person CodaFi; 01.03.2013
comment
@CodaFi Проблема в том, что автор этого ответа прочитал только заголовок, а не вопрос. - person ; 01.03.2013