views:

513

answers:

4

I asked a similar question, but I couldn't get it working exactly. I'm building an iPhone app, and there is a method that I want called from different files. I figured the easiest way would simply be to make a method in another file, and call the method from the other files.

Here are some problems. I need to return multiple values from the method, after passing it multiple values. For example, I'm passing it: (int, int, int, string, string). And it needs to return all of those values, after they have been changed. Someone showed me this code:

- (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness
{
    varTurns--;

    if (varTurns <= 0) {
     varFatness = varFatness - 5;
    }
    else {
     varFatness += 2;
    }

    return [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:varFatness], @"FATNESS", [NSNumber numberWithInt:varTurns], @"TURNS", nil];

}

However, this code doesn't work, and I need some more information to really understand it. Let's assuming I'm passing it these values:

int varMoney;
int varNumSheep;
int varNumShepherds;
NSString *test1;
NSString *test2;

So I need to get all of these values back from the method.

How do I declare this in the header file? This should be in an Objective-C file, but could you give me the code for the entire file so I can see where it would go with the @implementation and @end, whatnot. Also, how would I call this method?

+9  A: 

What about passing in the values as pointers?

For example:

- (void) getValuesForInt:(int *)int1 anotherInt:(int *)int2 aBool:(BOOL *)bool1 anotherBool:(BOOL *)bool2 {
  if (*int1 == 42 && *int2 == 0) {
    *int1 = 0;
    *int2 = 42;
  }
  if (*bool1 == NO) {
    *bool2 = YES;
  }
}

Then you can invoke it like:

int int1 = 42;
int int2 = 0;
BOOL bool1 = NO;
BOOL bool2 = NO;
[self getValuesForInt:&int1 anotherInt:&int2 aBool:&bool1 anotherBool:&bool2];
NSLog(@"int1: %d int2: %d bool1: %d bool2: %d", int1, int2, bool1, bool2);
//prints "int1: 0 int2: 42 bool1: 0 bool2: 1"

Edit:

This works equally well with objects. You'll often see this used when dealing with NSError objects:

NSError *error = nil;
[anObject doSomething:foo error:&error];

Can be implemented as:

- (void) doSomething:(id)terrible error:(NSError **)error {
  if ([terrible isEqual:reallyBad]) {
    if (error != nil) { *error = [NSError errorWithDomain:@"domain" code:42 userInfo:nil]; }
  }
}
Dave DeLong
It should be *int2 == 0. Also your NSLog line is missing the parameters.
Chris Suter
I think the other solution is a little more effective, I tried that earlier but it didn't work well with strings.
Wayfarer
@Chris whoops! that's what i get for typing code in the browser. =)
Dave DeLong
@Wayfarer edit answer to give an example of how this would work with objects.
Dave DeLong
+2  A: 

Since you can only return a single value from any method in C and C-derived languages, you simply need to return a single value that represents all of your other values. This is what your sample code is doing with an NSDictionary.

The sample code is correct, even if it's a bit contrary to common Objective-C style.

What you declare in the header file is simply the declaration of the method, that is:

@interface MyClass : NSObject
- (NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness;
@end

In the source file, then:

@implementation MyClass
// code, as given above
@end
Jim Puls
Kk, I'll try that out.
Wayfarer
Okay, what is the syntax for calling this function? I've imported the header file already, but when I try calling the function it says "Expected : Before : token. This the call:(NSDictionary *)EndOfTurn:(int)varTurns withFatness:(int)varFatness; I'm passing it the Variables "varTurns" and "varFatness"
Wayfarer
Your call should look like [object EndOfTurn:varTurns withFatness:varFatness] - the (int) bits are just for the definition, not the call.
Kendall Helmstetter Gelner
+5  A: 

If you have that many different things that need to be returned from a method, either encapsulate it into an NSDictionary as others have suggested or consider just defining a class. You can declare the instance variables and properties to encapsulate the data, as needed.

Defining a class to encapsulate such information proves to be quite efficient and maximizes flexibility. If you need to refactor your app such that the collection of data gains new fields, needs to be saved for later, or might need to gain functionality, a class will ease these changes.

bbum
+1 for creating a new class. @Wayfarer: embrace the world of OOP.
mahboudz
A: 

Jim pulse wrote:

" Since you can only return a single value from any method in C and C-derived languages you simply need to return a single value that represents all of your other values. "

I do not agree completely with you jim. In languages like C and C++ it's true than you can only return a single value. but a method could "return" more than a single result passing values by reference (or pointers)!!

example:

int method(void); this method can return only one value!!

void method(int& a,int& b, int& c); this one can t return any value, but it has three values (a,b,c) "visible" in the scope of the caller.

I'm looking for a similar way to do the same thing in Objective C because in my code it was a very common (and very usefull) practice.

Andy
See Dave DeLong's answer, this is exactly what he suggested and what's actually a much cleaner way than returning an NSDictionary.
Pascal