Передача Массива По Ссылке В Objective-C


Я хотел бы передать NSMutableArray по ссылке, чтобы его можно было изменить другим методом. Каков был бы правильный синтаксис для этого?

Спасибо,

3   4  

3 ответа:

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

То есть прекрасно следующее:

- (void)mutateArray:(NSMutableArray*)array {
    // alter array ...
}

... и может быть, например, вызван следующим образом:

NSMutableArray *array = ...;
[self mutateArray:array];

Существует также возможность передачи указателя по ссылке:

- (void)newArray:(NSMutableArray **)array;

В этом случае array используется в качестве out-параметра-вы передаете ссылку на указатель, чтобы получить экземпляр:

- (void)newArray:(NSMutableArray **)array {
    *array = [[NSMutableArray alloc] init];
}

... который можно было бы назвать так:

NSMutableArray *array = nil;
[self newArray:&array];

Использование out-parameters обычно отображается только в том случае, если возвращаемое значение уже используется и требуется вернуть дополнительную информацию. Примером может служить информация об ошибках, как отметил dreamlax.

В дополнение к ответу Георга Фрицше, возможно, стоит отметить, что некоторые методы ожидают, что им будет дан адрес указателя объекта. Например:

NSError *anError; // points to garbage now
NSStringEncoding enc;
NSString *aString = [NSString stringWithContentsOfFile:@"/some/file.txt"
                                          usedEncoding:&enc
                                                 error:&anError];

if (aString == nil)
{
    // anError now points to an initialised NSError object.
}

Это становится сложным, потому что некоторые документированные методы требуют, чтобы вы освобождали объекты, полученные таким образом, а некоторые нет (пример одного, который требует явного освобождения, см. NSPropertyListSerialization).

Как сказал Георг Фриц, NSMutableArray передается автоматически, но не NSArray. Лучший вариант-тоже посмотреть на код ниже:

void mutateImmutableArray(NSArray *array);
void mutateMutableArray(NSMutableArray *array);
void mutateImmutableArrayByRef(NSArray **array);
void mutateMutableArrayByRef(NSMutableArray **array);

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //Change immutable array in method that expects immutable array
        NSArray *immutable = @[@1,@2,@3];
        mutateImmutableArray(immutable);
        NSLog(@"After 1: %@",immutable); // 1,2,3

        //Change mutable array in method that expects immutable array
        NSMutableArray *mutable = [@[@1,@2,@3]mutableCopy];
        mutateImmutableArray(mutable); 
        NSLog(@"After 2: %@",mutable); //1,2,3

        //Change mutable array in method that expects mutable array
        mutable = [@[@1,@2,@3]mutableCopy];
        mutateMutableArray(mutable); 
        NSLog(@"After 3: %@",mutable); //1,2,3, Four

        //Change immutable array in method that expects immutable array by reference
        immutable = @[@1,@2,@3];
        mutateImmutableArrayByRef(&immutable); 
        NSLog(@"After 4: %@",immutable); //4,5,6

        //Change mutable array in method that expects mutable array by reference
        mutable = [@[@1,@2,@3]mutableCopy];
        mutateMutableArrayByRef(&mutable); 
        NSLog(@"After 5: %@",mutable); //1,2,3, Four

    }
    return 0;
}

void mutateImmutableArray(NSArray *array)
{
    array  = @[@4,@5,@6];
}

void mutateImmutableArrayByRef(NSArray **array)
{
    *array  = @[@4,@5,@6];
}

void mutateMutableArray(NSMutableArray *array)
{
    [array addObject:@"Four"];
}

void mutateMutableArrayByRef(NSMutableArray **array)
{
    [*array addObject:@"Four"];
}