Returning result from method

Discussion in 'iOS Programming' started by jca69, Dec 17, 2013.

  1. jca69 macrumors newbie

    Joined:
    Jun 13, 2013
    Location:
    Vancouver, BC
    #1
    This will seem a dumb question, but as I've spent too much time doing ABAP, I'm afraid my C/Objective-C skills are pretty rusty.

    I'm not sure if I'll ever produce any interesting app on the App Store, but anyways, I'm kind of having fun playing around with Xcode, Objective-C and the iPhone.

    So here's the thing. I'm following Paul Hegarty's lessons on iTunes U and while trying to solve the exercises/enhancements to his programs, I came across the following conundrum.

    In one class I have the following method:

    Code:
    -(NSString *)doStuff {
    
        NSString *result;
        
        result = nil;
        ...
        if (...) {
            ...
            result = [NSString stringWithFormat:@"You won %d points!", points];
        } else {
            result = [NSString stringWithFormat:@"You lost %d points!", points];
        }
        ...
        return result; 
    }
    
    In another class that calls the one above:

    Code:
    @property (weak, nonatomic) IBOutlet UILabel *infoLabel;
    
    - (IBAction)cardSelected:(UIButton *)sender {
        NSString *result;
    
        result = [self.myGame doStuff];
        self.infoLabel.text = result;  // or self.infoLabel.text = [self.myGame... ]; for short
        [self refreshUI];
    
    }
    
    This works, result in cardSelected receives whatever is put in the string in doStuff.
    However, when I first tried getting the result in cardSelected not as myGame return value but as an argument, result is always null. The code would be the following:

    Code:
    -(void)doStuff:(NSString *)result {
        
        result = nil;
        ...
        if (...) {
            ...
            result = [NSString stringWithFormat:@"You won %d points!", points];
        } else {
            result = [NSString stringWithFormat:@"You lost %d points!", points];
        }
        ...
    }
    
    And the call looked something like this:

    Code:
    @property (weak, nonatomic) IBOutlet UILabel *infoLabel;
    
    - (IBAction)cardSelected:(UIButton *)sender {
        NSString *result;
    
        [self.myGame doStuff:result];
        self.resultLabel.text = result;
        [self refreshUI];
    
    }
    
    If the string is allocated in doStuff in both cases, why is not passed to the argument in cardSelected?
    Thanks
     
  2. ohbrilliance macrumors 6502a

    ohbrilliance

    Joined:
    May 15, 2007
    Location:
    Melbourne, Australia
    #2
    Your first approach is attempting to assign the value by reference, but you haven't written the syntax correctly. To do so:

    Code:
    -(void)doStuff:(NSString **)result {
         ...
        if (...) {
            ...
            *result = [NSString stringWithFormat:@"You won %d points!", points];
        } else {
            *result = [NSString stringWithFormat:@"You lost %d points!", points];
        }
        …
    }
    Then call doStuff like this:

    Code:
        [self.myGame doStuff:&result];
    
    However, this entire approach is wrong. There's no point in assigning a value by reference for a simple function that only needs to return a string.
     
  3. jca69 thread starter macrumors newbie

    Joined:
    Jun 13, 2013
    Location:
    Vancouver, BC
    #3
    Right, the double indirection!! Thanks, and I agree, in this case/language, it doesn't make sense to return the result passing the reference in the argument.
     
  4. iMacFarlane macrumors 65816

    iMacFarlane

    Joined:
    Apr 5, 2012
    Location:
    Adrift in a sea of possibilities
    #4
    Looking at your code, it looks like there is a syntax error bolded below:

    Code:
    @property (weak, nonatomic) IBOutlet UILabel *infoLabel;
    
    - (IBAction)cardSelected:(UIButton *)sender {
        NSString *result;
    
        [B][self.myGame doStuff:result];[/B]
        self.resultLabel.text = result;
        [self refreshUI];
    
    }
    In your definition of doStuff, there is no declaration for data to be passed into the function, which is where you would then use a colon :)) following the function name to do so. The line "[self.myGame doStuff:result];" is trying to send result, but doStuff is not coded to receive any data.

    I think what you meant to do, was execute doStuff and have it return it's data to result. In that case, the following code is more appropriate:

    Code:
    @property (weak, nonatomic) IBOutlet UILabel *infoLabel;
    
    - (IBAction)cardSelected:(UIButton *)sender {
        NSString *result;
    
        [B]result = [NSString stringWithFormat: @"%@", [self.myGame doStuff]];[/B]
        self.resultLabel.text = result;
        [self refreshUI];
    
    }
     
  5. waterskier2007 macrumors 68000

    waterskier2007

    Joined:
    Jun 19, 2007
    Location:
    White Lake, MI
    #5
    Actually, OP was just trying to pass result by reference so that it was modified within the doStuff method
     
  6. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #6

    C, and hence Objective C, always passes parameters by value. There is no direct support for passing values by reference.

    I did quite a bit of Pascal programming on Mac before OSX. Pascal lets you declare parameters as either by value or by reference as part of of the function definition. No such thing in C/Objective-C however.

    As the other poster said, if you want to pass an object by reference, you need to use pointer-to-pointer syntax.

    Note that this is generally frowned upon. It makes the code hard to follow. There are rare cases where you need this syntax (a method that needs to return multiple objects) but there is almost always a better way to handle it (e.g. returning a dictionary that contains the multiple result objects)
     
  7. jca69, Dec 18, 2013
    Last edited: Dec 18, 2013

    jca69 thread starter macrumors newbie

    Joined:
    Jun 13, 2013
    Location:
    Vancouver, BC
    #7
    No, no syntax error, both versions of the code compiled, maybe I missed something in the code while posting it here. It's just that, like waterskier2007 said, I was trying to pass result by reference without much success, a very un-C practice, according to what I'm reading here.

    I remember that feature from Pascal. And in ABAP, by default everything is passed by reference, so I guess I'm "speaking" Objective-C with a thick accent :D
     

Share This Page