What does the "*" mean in Objective C? - objective-c

Sometimes I encounter code that has *, sometimes **. Can anyone explain what they mean in Objective C? (I used to be a Java programmer, with experience in C/C++.)

The * denotes that you are using a pointer to a variable, and is most commonly used to store a reference to an Objective-C object, objects which can only live on the heap and not the stack.
Pointers are not a part of Objective-C exclusively, but rather a feature of C (and therefore its derived languages, of which Objective-C is one of them).
If you are questioning the difference between * and **, the first denotes a pointer, whereas the second denotes a pointer to a pointer; the advantage of the latter to the former is that when passing in an object using ** in a method parameter, the method can then change this parameter and the new value is accessible in the calling method.
Perhaps the most common use of ** in Cocoa is when using NSError objects. When a method is called that can return an NSError object on failure, the method signature would look something like this:
- (id)someMethodThatUsesObject:(id)object error:(NSError**)error;
What this means is that the calling function can pass in a pointer to an NSError object, but someMethodThatUsesObject: can change the value of error to another NSError object if it needs to, which can then be accessed by the calling method.
This is often used as a workaround for the fact that functions can only return one value.

A * in Objective-C means exactly the same as in C; and you'll usually see it (or not) in these situations:
// Method signatures:
// Here the asterisk (*) shows that you have a pointer to an NSString instance.
+ (NSString *)stringWithString:(NSString *)aString;
// Method signatures, part two:
// Here the double asterisk (**) signifies that you should pass in a pointer
// to an area of memory (NSError *) where outError can be written.
- (BOOL)writeToURL:(NSURL *) atomically:(BOOL) error:(NSError **)outError;
// Method signatures make for good examples :)
// Here the asterisk is hidden; id is a typedef for void *; and it signifies that
// a pointer to some object of an indeterminate class will be returned
- (id)init;
// And a forth example to round it all out: C strings!
// Here the asterisk signifies, you guessed it, a pointer! This time, it's a
// pointer to the first in a series of const char; terminated by a \0, also known
// as a C string. You probably won't need to work with this a lot.
- (const char *)UTF8String;
// For a bit of clarity, inside example two, the outError is used as follows:
// Here the asterisk is used to dereference outError so you can get at and write
// to the memory it points to. You'd pass it in with:
// NSError *anError;
// [aString writeToURL:myURL atomically:YES error:&anError];
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atom error:(NSError **)outError {
// do some writing, and if it went awry:
if (outError != NULL)
*outError = [NSError errorWithName:#"NSExampleErrorName"];
return NO;
}

Related

Are Objective-C Objects Pass By Value or Pass By Reference?

So I have something like :
- (void) printString:(NSString *)string
{
NSLog(#"%#", string);
}
NSString *string = #"Blach";
[self printString:string];
Would string be passed in by value or reference? What about something like NSError?
NSError *error = [NSError errorWithDomain:someDomain
code:-101
userInfo:someInfo];
-(NSString *) doSomething:(BOOL) val withError:(NSError **)error {
if(!val)
{
*errorPtr = [NSError errorWithDomain:something
code:-101
userInfo:someInfo];
}
}
You can never refer to an Objective-C object by anything other than a pointer, so for all intents and purposes, everything is pass-by-reference. That said, the actual pointer values are passed by value, just like in C.
Everything of every type in Objective-C is pass-by-value only.
The question is invalid because "objects" are not values in Objective-C and therefore cannot be "passed" -- you cannot have a variable or expression whose value "is an object" (a bare object type is not allowed in the language) -- instead, "objects" must always be manipulated behind pointers to objects. Since "objects" are not values and you cannot "pass" them, it is meaningless to ask about whether they are "pass-by-value" or "pass-by-reference".
Objects are passed by reference. The important distinction, to my mind, is whether the called method has a reference to the same object as the caller or if it has a copy. It has a reference to the same object.
If the object is mutable and the called method mutates it, it affects the object that the caller has, too (because it's the same object).
In the case of an NSError** parameter, it is actually the pointer (not an object) which is being passed by reference. A method with such a parameter can actually modify the caller's pointer, making it point to a different object.

Implicit ownership qualifier for parameters/return type is always __strong?

Since in projects with automatic reference counting NSString * aString; means implicitly NSString * __strong aString;. Does it also count for the parameters and return types?
Is
- (NSString *)doubleString:(NSString *)aString {
return [NSString stringWithFormat:#"%#%#", aString, aString];
}
the same compiled code as
- (NSString * __strong)doubleString:(NSString * __strong)aString {
return [NSString stringWithFormat:#"%#%#", aString, aString];
}
and in every similar method?
Short answer: Yes. Both variants produce the same compiled code, as can be verified
by "Product -> Perform Action... -> Assemble ..." from the Xcode menu.
Longer answer: (The following references and citations are from the Clang/ARC documentation.)
Your question about the return value. According to
"4 Ownership qualification",
qualifiers like __strong and __weak apply to locations in memory where a pointer
to an object is stored, and they specify the semantics when loading from or storing to
an lvalue (4.2 Semantics).
The return value of a method is not such a location in memory (it is not an lvalue),
therefore the concept of ownership qualification does not apply here.
It makes not differences if the method is declared as returning (NSString * __weak) or (NSString * __strong), there is no difference in the compiled code.
A slightly different question is whether the caller owns the
returned object (it has a +1 retain count) or not. This depends by default on the method name, as explained in "3.2.2 Retained return values"
and "3.2.3 Unretained return values".
Your question about the parameters. Declaring the parameter as
(NSString * __strong) is identical to (NSString *). This can already be seen
from the Xcode autocompletion (where the "__strong" qualifier is not shown), but
also from the generated Assembly code.
This does not mean that arguments are retained when calling a method.
By default, they are not, as explained in
"3.2 Retainable object pointers as operands and arguments".
If an parameter is declared as __weak, it seems (from the Assembly code) that a temporary weak reference is created in the method, i.e.
- (NSString *) doubleString:(NSString * __weak)aString {
return [NSString stringWithFormat:#"%#%#", aString, aString];
}
is essentially the same as
- (NSString *) doubleString:(NSString *)aString {
NSString *__weak wString = aString;
return [NSString stringWithFormat:#"%#%#", wString, wString];
}
But I was not able to find a definite reference for this.

Double pointer as Objective-C block parameter

Is it possible (and if so, safe) to create/use a block which takes a double pointer as an argument?
For instance:
- (void)methodWithBlock:(void (^)(NSError **error))block;
Additional context, research, and questions:
I'm using ARC.
When I declare the method above and attempt to call it, XCode autocompletes my method invocation as follows: [self methodWithBlock:^(NSError *__autoreleasing *error) {}];
What does __autoreleasing mean here and why is it being added? I presume it has something to do with ARC.
If this is possible and safe, can the pointer still be dereferenced in the block as it would be anywhere else?
In general, what are the important differences between doing what I'm describing, and simply passing a double pointer as a method parameter (e.g. - (void)methodWithDoublePointer:(NSError **)error;)? What special considerations, if any, should be taken into account (again assuming this is possible at all)?
yes, pointers are always just pointers. you only need to make sure you dereference it before sending it a message (assuming objc object).
Also be aware that the pointer may be nil. always check it before trying to dereference it or what have you.
As #verec mentioned if you are using ARC you should declare the parameter as __autoreleasing
according to the docs
__autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.
remember id is a pointer to an object so that is saying object**
there is no difference between passing pointers to pointers to methods or blocks.
The answers are both Yes & No...
At a base level passing pointers to pointers to blocks is no different than passing them to methods; and, with the usual proviso that your pointers must be valid, is perfectly OK.
However that __autoreleasing is very significant here and is tied up with ARC and pass-by-writeback. Whether using the block will work as expected will be dependent on context as the compiler often uses hidden variables when passing parameters of type NSError * __autoreleasing * as part of the pass-by-writeback implementation.
If pass-by-writeback is not what you need, or is unsuitable, you may wish to declare you block as taking a different type, such as NSError * __strong *. Read this answer which explains what happens under the hood, that should help you decide whether in your context the block declaration is good.
In summary (a) declaring the block is fine, but (b) you need to understand how it may be called and may need to change the signature.
warning: untested
For the sake of argument, let's start with:
typedef NSError * NSErrorPtr ;
- (void) foo: (NSErrorPtr *) errPtr {
*errorPtr = [NSError new] ;
}
errPtr isn't declared either __weak nor __strong.
So, according to ARC, even though its contents is allocated within foo the responsibility for releasing it has to reside somewhere.
Where?
Note that this not a property of double pointers per se. But of your pattern of allocation.
consider:
int ** arrayOfarrayOfInts = {
{1, 2, 3, 4}
, {5, 6, 7, 8}
} ;
- (void) incrementElement: (int **) elem {
++(**elem) ;
}
- (void) bumpFirstColByOne {
for (int i = 0 ; i < 2 ; ++ i) {
int * arrayOfInt = arrayOfarrayOfInts[i] ;
int ** second = &arrayOfInt[0] ;
[self incrementElement: second] ;
}
}
No __autoreleasing needed here because no allocation is taking place ...

NSFastEnumeration object casting in ARC

I'm trying to implement the countByEnumeratingWithState:objects:count: method from the NSFastEnumeration protocol on a custom class.
So far I have it iterating through my objects correctly, but the objects that are returned aren't Objective-C objects but rather the core foundation equivalents.
Here's the part of the code that sets the state->itemsPtr:
MyCustomCollection.m
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
objects: (id __unsafe_unretained *)buffer
count: (NSUInteger)bufferSize {
// ... skip details ...
NSLog(#"Object inside method: %#", someObject);
state->itemsPtr = (__unsafe_unretained id *)(__bridge void *)someObject;
// ... skip details ...
}
Then I call the 'for..in' loop somewhere else on like this
SomeOtherClass.m
MyCustomCollection *myCustomCollection = [MyCustomCollection new];
[myCustomCollection addObject:#"foo"];
for (id object in myCustomCollection) {
NSLog(#"Object in loop: %#", object);
}
The console output is:
Object inside method: foo
Object in loop: __NSCFConstantString
As you can see, inside the NSFastEnumeration protocol method the object prints fine, but as soon as it gets cast to id __unsafe_unretained * I lose the original Objective-C corresponding class.
To be honest I'm not quite sure how the (__unsafe_unretained id *)(__bridge void *) casting works in this case. The (__unsafe_unretained id *) seems to cast to match the right type itemsPtr needs. The (__bridge void *) seems to cast to a pointer of type void with __bridge used to bridge the obj-c world to the CF world. As per the llvm docs, for __bridge:
There is no transfer of ownership, and ARC inserts no retain operations
Is that correct?
From my understanding __NSCFConstantString is just the core foundation equivalent of NSString. I also understand that with ARC you need to bridge from Objective-C objects to CoreFoundation equivalents because ARC doesn't know how to manage the memory of the latter.
How can I get this working so that the objects in my 'for..in' loop are of the original type?
Also note that in this case I'm adding NSStrings to my collection but in theory it should support any object.
UPDATE
Rob's answer is on the right track, but to test that theory I changed the for loop to this:
for (id object in myCustomCollection) {
NSString *stringObject = (NSString *)object;
NSLog(#"String %# length: %d", stringObject, [stringObject length]);
}
In theory that should work since the objects are equivalent but it crashes with this error:
+[__NSCFConstantString length]: unrecognized selector sent to class
It almost looks like the objects returned in the for loop are classes and not instances. Something else might be wrong here... Any thoughts on this?
UPDATE 2 : SOLUTION
It's as simple as this: (thanks to CodaFi
state->itemsPtr = &someObject;
You're incorrectly casting someObject. What you meant is:
state->itemsPtr = (__unsafe_unretained id *)(__bridge void *)&someObject;
(Let's get rid of those awful casts as well)
state->itemsPtr = &someObject;
Without the address-of, your variable is shoved into the first pointer, which is dereferenced in the loop. When it's dereferenced (basically, *id), you get the underlying objc_object's isa class pointer rather than an object. That's why the debugger prints the string's value inside the enumerator call, and the class of the object inside the loop, and why sending a message to the resulting pointer throws an exception.
Your code is fine the way it is. Your debug output is revealing an implementation detail.
NSString is toll-free-bridged with CFString. This means that you can treat any NSString as a CFString, or vice versa, simply by casting the pointer to the other type.
In fact, under the hood, compile-time constant strings are instances of the type __NSCFConstantString, which is what you're seeing.
If you put #"hello" in your source code, the compiler treats it as a NSString * and compiles it into an instance of __NSCFConstantString.
If you put CFSTR("hello") in your source code, the compiler treats it as a CFStringRef and compiles it into an instance of __NSCFConstantString.
At run-time, there is no difference between these objects in memory, even though you used different syntax to create them in your source code.

Objective-c symbols ** & +-

Just when I think I'm getting comfortable with Objective-c the mentioned symbols totally throw me down a rabbit hole...
** a double pointer??
& what sort of things can I do with &reference, is a #property? a full on object? weird pointer razzledazzle?
± I see both a + or a - before method declarations; I've seen Java annotate some datatype declarations by manually typing the + and the magic of compiling in Eclipse would change them to a -
I'm likely asking repetitious questions and/or way outta the ballpark on my guesses; thanks for answers/edits.
You're getting into the C portion that objective-c is built on top of.
** is a pointer to a pointer. Since functions in C take arguments by value, it means you can't change the value of the argument in that function. But, by providing a level of indirection and passing a pointer to the pointer, you can change the value.
& means it's a reference. If an argument takes a ** and you have a * variable, pass a reference to it.
Foo *foo;
[self changeFoo: &foo];
- (BOOL)changeFoo: (Foo **)foo
{
// dereference the double pointer and assign a val = alloc init returns a *
*foo = [[Foo alloc] init];
return YES;
}
A common usage in objective-c / cocoa is NSError. It's essentially an out argument.
NSError *err;
BOOL success = [self doSomething:#"Foo" error:&err];
- (BOOL)doSomething:(NSString*)withData error:(NSError**)error
{
}
As you might know, a pointer points to the address of an object and is the way you reference an object. A double pointer is sometimes used in Objective-C, mainly for returning NSErrors, where you want to get back the address, i.e. a pointer, to an error object (NSError) if an error occurred, thus you pass in a pointer assigned to null and the caller can change that pointer so that it points to the address of another pointer which in turn points to an NSError object.
The ampersand (&) is mostly used by the lower level C APIs, e.g. Core Graphics. They are used to reference things, like the current context. As long as most of your code uses square brackets around its method calls you won't see these very often.
Using a + or a - before a method declarations is used to differentiate between class (+) and instance (-) methods. A class methods is called on the class itself (such as alloc), while a instance method is called on an instance of that object (such as init).
- and + before a method declaration designate an instance method and a static class method. To use an instance method you have to create an object of your class before you can call its method, a static method can be called directly from a class type