5

I have a method that takes an NSMutableArray as a parameter, and I would like it to return that array, another array that is created in the method, and an int created by the method. I realize this could be done by making an array that had all these objects in it, and returning that, then removing them from the array outside the method, but is there another way to return multiple objects?

1
  • So basically the easiest way to do this is going to just be putting the values in a dictionary or array. Commented Sep 13, 2010 at 1:02

4 Answers 4

9

The typical ways to pass back multiple values are to:

  • Add extra parameters by reference (ex. typically NSErrors are passed this way)
  • Pass them back in some other struct or object, typically an NSDictionary or a custom class

The above are good solutions for many situations, but here is another solution that may work best in other situations:

Add a block to your method:

- (void)myMethodWithMultipleReturnObjectsForObject:(id)object returnBlock:(void (^)(id returnObject1, id returnObject2))returnBlock
{
    // do stuff

    returnBlock(returnObject1, returnObject2);
}

Then use the method like this:

[myMethodWithMultipleReturnObjectsForObject:object returnBlock:^(id returnObject1, id returnObject2) {
    // Use the return objects inside the block
}];

The return objects in the above example are only usable within the block, so if you want to keep them around for use outside the block, just set some __block vars.

// Keep the objects around for use outside of the block
__block id object1;
__block id object2;
[myMethodWithMultipleReturnObjectsForObject:object returnBlock:^(id returnObject1, id returnObject2) {
    object1 = returnObject1;
    object2 = returnObject2;
}];
Sign up to request clarification or add additional context in comments.

2 Comments

Can you explain a little bit more abut that? How could I declare the block in this case?
@Tulon I'm not sure what you mean. I already show the block's declaration in the first chunk of code in my example.
7

Using an NSDictionary to return multiple values is the customary way to do this in Obj-C.

The method signature would look something like this:

-(NSDictionary *)doSomeStuffThatReturnsMultipleObjects;

and you are going to want to define your dictionary keys in the appropriate files.

// Header File
extern NSString *const JKSourceArray;
extern NSString *const JKResultsArray;
extern NSString *const JKSomeNumber;

// Implementation File
NSString *const JKSourceArray = @"JKSourceArray";
NSString *const JKResultsArray = @"JKResultsArray";
NSString *const JKSomeNumber = @"JKSomeNumber";

The advantage over using an array is that the the order of elements and the presence/absence of elements doesn't matter, making it far easier to extend in the future, if you want to return additional objects. It's also far more flexible and extensible than passing by reference.

Comments

2

Another way you can do it is have the user pass a pointer which they want to use to hold the data. Here is a sample that returns an array and uses pointers to give you an int value and another array. EDIT ok here is the working version I just tested it myself:

- (NSMutableArray*)doStuff:(int*)container returnedArray:(NSMutableArray*)arrayContainer{
   int a = 4;
   *container = a;
   [arrayContainer removeAllObjects];
   [arrayContainer addObject:@"object"];
   return [NSMutableArray arrayWithObjects:@"object",nil];
}

That way you could say like:

int value = 0;
NSMutableArray* new = [NSMutableArray array];
[self doStuff:&value returnedArray:new];

And it basicly works like a return!

11 Comments

Although the general technique you describe is one that's used in real programs, that code is totally broken and will not do what is intended at all. You seem to have some misconceptions about how pointers work, and also about variable scope.
Yeah, I thought this seemed a little off. Thanks for the idea though.
@Chuck I didn't test it I was just giving a sample of the concept and I wrote that in very little time. I was just trying to get him in the right direction.
@Chuck some of my wording might be a little off but the basics should work.
@Regan like chuck said it really does work you might just want to find a better example...
|
0

You might want to consider returning a struct.

typedef struct {
    NSMutableArray *array1;
    NSArray *array2;
    NSInteger integer;
} MyAwesomeReturnValue;

Your method could now look like this:

- (MyAwesomeReturnValue)myAwesomeMethod:(NSMutableArray *)parameter
{
    MyAwesomeReturnValue retval;
    retval.array1 = parameter;
    retval.array2 = [NSArray array];
    retval.integer = 5;

    return retval;
}

And you'd use it like:

- (void)anotherAwesomeMethod
{
    NSMutableArray *array = [NSMutableArray array];
    MyAwesomeReturnValue returnedValue = [self myAwesomeMethod:array];

    NSLog(@"%@", returnedValue.array1);
    NSLog(@"%@", returnedValue.array2);
    NSLog(@"%d", returnedValue.integer);
}

Hope that helped. ;)

6 Comments

I don't like the myAwesomeMethod example. You are creating a local parameter named retval, and returning that as the result. But as soon as you pop the stack, you lose that local parameter. It would be different if that was an object, but this is just a standard C struct.
@Christian Schnorr, How could you set NSMutableArray in struct. There should be an error.
@Tulon How? NSMutableArray is a subclass of NSArray?
@Rickster Just came back to this. Wouldn't the structure be copied once returned from the method though, hence actually being safe?
@ChristianSchnorr, ARC enable code and you will get Error: ARC forbids Objective - C objects in struct at line NSMutableArray *array1; in typedef struct...
|

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.