SundayMonday
SundayMonday

Reputation: 19727

Objective-c syntax for passing a c-style array of NSStrings

What's the best syntax for passing a c-style array containing NSString* to an objective-c method? Here's what I'm currently using:

- (void) f:(NSString **) a {

}

- (void) g {
    NSString* a[2] = {@"something", @"else"};
    [self f:a];
}

Upvotes: 4

Views: 2530

Answers (3)

CRD
CRD

Reputation: 53000

Slightly better is:

- (void) f:(NSString *[]) a

as it makes it clear it is expecting an array (passed by reference) of references to NString, rather than a reference to a reference to an NString.

However this will in all probability not change the compiler's type checking, you could pass an NSString ** without issue. The same goes if you add a bounds:

- (void) f:(NSString *[2]) a

Here the compiler will in all probability just ignore the 2 - both when calling and inside the body, you're just adding a "comment". (If you are passing multi-dimensional arrays you do need to specify all but the last index.)

Addendum

Prompted by Mike Keskinov (see comments)

Update for ARC

Under ARC the declaration in the question:

NSString* a[2] = {@"something", @"else"};

which has no explicit ownership qualifier is treated as:

NSString* __strong a[2] = {@"something", @"else"};

that is an array of strong references to strings. When a pointer to a variable itself is passed, in this case a pointer to an array, the compiler needs to know the ownership qualification of the pointed-at variable. At the time of writing in the case of pointer to an array the compiler has no default so the declaration in this answer above:

- (void) f:(NSString *[]) a

will produce the error, as reported by Mike Keskinov in the comments below, and you must insert an explicit ownership qualifier:

- (void) f:(NSString * __strong []) a

With that information the compiler knows how to automatically handle the string references in the array – in the body of f the compiler will automatically as required retain and release NSString references.

For more details on ARC and pointers to variables/pointers see Handling Pointer-to-Pointer Ownership Issues in ARC and NSError and __autoreleasing.

Use For Constant Arrays

Though not part of the original question is it clear that many are using C arrays as a means of having an array of string constants in Objective-C. For this particular use observe:

  1. If the array and parameter types are declared as arrays of constant references to strings then the array elements cannot be changed;

  2. Making the array static will also ensure it is only create and initialised once, even if declared with a function; and

  3. If your C array contains only string literals then the default __strong ownership qualifier is not required as string literals are immortal. Instead the __unsafe_unretained qualifier may be used, the references in the array will always be valid.

These produce the code fragments:

static NSString * const __unsafe_unretained a[2] = {@"something", @"else"}; 

and:

- (void) f:(NSString * const __unsafe_unretained[]) a

and you have the goal of a constant array of constant NSString literals. The compiler will not allow the array to be modified, or insert redundant memory management calls.

Upvotes: 2

Matt Wilding
Matt Wilding

Reputation: 20153

Your only other option is the following:

- (void) f:(NSString* []) a {

}

It's identical when compiled. I don't know about "best", but I prefer this version's readability. It's easier to infer that the pointer you're passing is intended to be used as an array. Pointers to pointers have different uses elsewhere (see the various NSError** parameters used in the iOS SDK), so the distinction is helpful.

Upvotes: 6

Dave Wood
Dave Wood

Reputation: 13333

The best way would be to use an NSArray instead of a c-style array.

Upvotes: 0

Related Questions