Out parameters in ARC Objective-C
Asked Answered
S

1

5

I'm using Objective-C, and I don't know how to create and call a method with out parameters when compiling the code with the ARC compiler.

This is the kind of thing I'm trying to accomplish in non-ARC Objective-C (this is probably wrong anyway).

//
//  Dummy.m
//  OutParamTest

#import "Dummy.h"

@implementation Dummy

- (void) foo {
    NSString* a = nil;
    [self barOutString:&a];
    NSLog(@"%@", a);
}

- (void) barOutString:(NSString **)myString {
    NSString* foo = [[NSString alloc] initWithString:@"hello"];
    *myString = foo;
}

@end

I've read the documentation here: https://clang.llvm.org/docs/AutomaticReferenceCounting.html

and here: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

...but am finding it difficult to get anything that compiles, never mind anything that is correct. Would anybody be able to rewrite the jist of the code above, in a way that is suitable for ARC Objective-C?

Scutate answered 12/10, 2011 at 12:56 Comment(8)
What exactly is your problem? What compiler errors do you get?Bibeau
I've updated the code sample above with your suggestions, and included the set of compiler errors. Thanks.Scutate
See my updated answer. As the compiler says, you cannot use an indirect pointer like that, instead you must pass in &a directly.Bibeau
Thanks for your help @MikeWeller, the code above compiles now - is it technically correct?Scutate
You don't need the b variable, just pass in &a as the argument. You also don't need to use __autoreleasing on the a and b variables unless you need to access the initial value in barOutString: which isn't very common.Bibeau
Yep, sorry, missed your comment. I was getting very muddled with the pointers there. Looks ok now then? Thanks.Scutate
NSString* foo = [[[NSString alloc] initWithString:@"hello"] autorelease]; Gives me "ARC forbids explicit message send of 'autorelease'" This compiles though: NSString __autoreleasing* foo = [[NSString alloc] initWithString:@"hello"];Scutate
Arg. What was I thinking? Sorry, yes the code is correct now. Of course you don't need autorelease with ARC -_-Bibeau
B
9

You need to use the __autoreleasing attribute on the out parameter:

- (void) barOutString:(NSString * __autoreleasing *)myString {
    NSString* foo = [[NSString alloc] initWithString:@"hello"];
    *myString = foo;
}

The prerelease documentation (which I'm not allowed to link to due to NDA) puts the __autoreleasing in the middle of the two '*'s, but it might just work as (__autoreleasing NSString **)

You also cannot use an indirect double pointer (b) as in your original code. You must use this form:

- (void) foo {
    NSString* a = nil;
    [self barOutString:&a];
    NSLog(@"%@", a);
}

You are also calling dealloc directly on an object which is completely wrong. I suggest you read the memory management guidelines.

Bibeau answered 12/10, 2011 at 14:6 Comment(2)
There's a small error in the first method. *myString = &foo; should be changed to *myString = foo;.Syncopated
Thanks, fixed. Not sure how that got in there.Bibeau

© 2022 - 2024 — McMap. All rights reserved.