1
// targ_url is passed in as an address to a NSString pointer.

- (long) analyse_scan_result : (NSString *)scan_result  target_url : (NSString **)targ_url

{

    NSLog (@" RES analyse string : %@", scan_result);

    NSRange range = [scan_result rangeOfString : @"http://"
                                 options       : NSCaseInsensitiveSearch
                     ];

    // **** The following retain is the first retain 
    // **** statement in this method.

    if (range.location == NSNotFound)
    {
        *targ_url = @"";
       [*targ_url retain];
        NSLog(@" FND string not found");
        return 0;
    }

    NSString *sub_string = [scan_result substringFromIndex : range.location];

    range = [sub_string rangeOfString : @" "];

    if (range.location != NSNotFound) {
        sub_string = [sub_string substringToIndex : range.location];         
    }

    NSLog(@"FND sub_string = %@", sub_string);

    *targ_url = sub_string;

    // ** The following retain is the second retain
    // ** statement in this method.

    [*targ_url retain];

    return [*targ_url length];

}

This question is similar and related to the one I asked earlier (which seems to be satisfactorily solved). Again, the above method only works after a retain statement is added. There are 2 added above, but only one is executed at any given time.

What the routine does is to find a "http://" string from a barcode scanner output and return it. My question is are the retain statements necessary or appropriate ?

Hope somebody knowledgable could help...

Community
  • 1
  • 1
Stanley
  • 4,446
  • 7
  • 30
  • 48

1 Answers1

2

TL;DR

Do not return owned object values by reference.

Explanation:

By convention, objects returned by reference (or even by value) are not owned unless the method specifically states this. If the method name contains copy or new then it is expected to provide an owned reference, otherwise the reference count is considered to be irrelevant.

For instance, Cocoa methods that return an NSError by reference return an autoreleased NSError which you are not expected to release.

What this means is, you can do either, as long as you indicate what you are doing via the method name. You probably just want to return an autoreleased reference and let the caller decide whether they want to keep holding on to it or not.

Apparently, Apple feels you should not return owned values by reference, according to this document:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html

yfrancis
  • 2,616
  • 1
  • 17
  • 26
  • Thanks for the answer, I actually tried both. But the strange part is if I do not retain in this method, I need to retain in the caller code but somehow I cannot release it without making the program crash. – Stanley Oct 31 '12 at 23:37
  • you shouldn't release something you don't own, in this case that behavior makes sense. Return an autoreleased NSString by reference, and the caller can use it and not have to worry about releasing it when it's done using it – yfrancis Oct 31 '12 at 23:40
  • About returning autoreleased NSString, do you mean I can return without the retain statements and it will become an autoreleased NSString to the caller ? – Stanley Oct 31 '12 at 23:44
  • Yep, `substringFromIndex` returns an autoreleased NSString, which you can just pass on by reference. If the caller wants to retain it for future use, they can. – yfrancis Oct 31 '12 at 23:46