4

I would like to pass a NSMutableArray by reference so that it can be altered by another method. What would be the correct syntax for this?

Thanks,

3 Answers 3

18

Objective-C objects are always passed by reference (using pointers) - you can't pass them by value.

I.e. the following is fine:

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

... and can be e.g. invoked like this:

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

There is also the possibility of passing a pointer by reference:

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

In that case array is used as an out-parameter - you pass a reference to a pointer to receive an instance:

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

... which could be called like so:

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

Using out-parameters is usually only seen if the return-value is already used and additional information has to be returned. An example would be error-information as dreamlax noted.

Sign up to request clarification or add additional context in comments.

1 Comment

What does it mean (using your above code as an example) when the following appears in a method declaration: - (void)mutateArray:(NSMutableArray **)array;?
4

In addition to Georg Fritzche's answer, it may be worth noting that some methods expect to be given the address of an object pointer. For example:

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.
}

It gets tricky because some documented methods require you to release objects obtained in this manner, and some don't (for an example of one that does require explicit releasing, see NSPropertyListSerialization).

1 Comment

Any method that requires you to release the returned pointer in this way should have explicit documentation, because it violates the fundamental rule of Cocoa reference counted memory management.
0

As Georg Fritzsche said NSMutableArray passed be reference automatically, but not the NSArray. The best option is too look at the code bellow:

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"];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.