& with variable [duplicate] - objective-c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why passing &error instead of error in Cocoa programming?
I have a question for which I cannot seem to find an answer...
I am using the SBJsonParser and there is a line of code I find puzzling:
NSError *error;
self.jsonData = [jsonParser objectWithString:responseString error:&error];
What is the & in front of the error parameter? (&error)?

In Objective-C, just like in C, & is the "address-of operator" and it returns the address of its argument. To find out more about it, I recommend you read this short chapter from The C Book.
Here's an example of how the operator is used, to get a better idea:
#include <stdio.h>
// define a function that takes a pointer to an integer as argument
void change_value_of_int(int* int_to_change) {
// change the value to which the argument points
*int_to_change = 5;
}
int main() {
// create a stack variable
int test_int = 10;
// pass the address of test_int to the function defined earlier
change_value_of_int(&test_int);
// now the value of test_int is 5
printf("%d\n", test_int);
return 0;
}
Note that the change_value_of_int() function expects the first parameter to be a pointer to an int, not an int, so you can't call it with change_value_of_int(test_int). You must send it the address of the test_int variable, not the variable itself (because if you send a copy of the variable, it can't change it).
Same thing with the NSError* example. jsonParser expects the address of a NSError*, not a NSError*, therefore the method is defined as:
- (id)objectWithString:(NSString*)jsonrep error:(NSError**)error;
Take a look at the header file and at the implementation to see how it is used. The value of your error (*error = the value of the thing pointed to by the error argument) becomes the return value of [errorTrace lastObject].

It's the address of operator, found in C, C++ and Objective-C.
In your example, &error yields a NSError ** (that is, a pointer to a pointer).
This is common in C (and, by extension, Objective-C): pass-by-reference is simulated with pointers, which means you have to pass the address of the object you want to modify (in this case, another pointer) to a function.

& is the address operator.
real quick lesson, all objects in Objective-C are pointers, which makes thing easy, because you know the level of indifference of everything, id is a special case, which a pointer to any object, without specifying class.
pointer to a pointer is most often used when returning an error, that is passed as a parameter to a method.
-(void)doSomething:(NSError**)err
{
//we have an error, return it.
*err = [NSError errorWithDomain:#"custom Domain" code:42 userInfo:nil];
}
then use the method with:
NSError * err = nil;
[self doSomething:&err];
if(err)
{
NSLog(#"we have an error in domain: %#",[err domain]);
}
which outputs:
we have an error in domain: custom
Domain
this is especially useful when you are returning something, as you can only return one value in C. This is exceptionally common is vanilla C and C++, but not used that much in Objective-C.

Related

Modify parameters in Objective-C blocks

I would like to modify various variables which exist outside an Objective-C block within it's body.
I know I can directly access and modify a variable using the __block attribute while declaring the variable. So this works:
__block NSMutableString *alertMessage;
void(^appendMessage)(NSMutableString*, NSString*)= ^(NSString *append){
if (!alertMessage)
{
alertMessage = [NSMutableString new];
}
if ([append length] > 0)
{
[alertMessage appendString:#"\n"];
}
[alertMessage appendString:append];
};
appendMessage(#"Alert part 1"); //This works fine
However I want to create a block which can perform an operation on a passed variable, enabling me to use the operation on multiple variables outside the block without directly accessing the same. Something like the following:
__block NSMutableString *alertMessage;
__block NSMutableString *otherString;
void(^appendMessage)(NSMutableString*, NSString*)= ^(NSMutableString *string, NSString *append){
if (!string)
{
string = [NSMutableString new];
}
if ([append length] > 0)
{
[string appendString:#"\n"];
}
[string appendString:append];
};
//The following do not work as intended
appendMessage(alertMessage, #"Alert Part 1");
appendMessage(otherString, #"Bleh bleh");
I want to be able to use the above block to modify the variables declared before it.
How can I achieve such an operation? Is this even possible?
Your question shows some confusion over values and variables, maybe the following will help.
Modify parameters in Objective-C blocks
In (Objective-)C all parameters to methods/functions/blocks are passed by value, e.g. when in the call f(x) the value of the variable x is passed to f, not the variable itself. This is known as call-by-value.
There are languages which do allow variables to be passed, known as call-by-reference. When used the argument must be a variable and the parameter name within the function is effectively an alias to the supplied variable. This is not supported directly in (Objective-)C.
However you can emulate it in (Objective-)C. It is not commonly used, with one notable exception: many methods use it to return an NSError * value.
You later comment:
What I want to achieve includes object creation, which is essentially what the question now boils down to. "Can I create an object declared outside within a block?". The answer which I have gathered with the help of all the activity here is NO.
You can, it is just a question of whether you should (i.e. is the design right?) and the best way to do it.
The straightforward way to solve your particular issue is to write a function:
NSMutableString *alertMessage;
NSMutableString *otherString;
NSMutableString *(^appendMessage)(NSMutableString *, NSString *) =
^(NSMutableString *string, NSString *append)
{
if (!string)
string = [NSMutableString new];
if (append.length > 0)
{
[string appendString:#"\n"];
[string appendString:append];
}
return string;
};
alertMessage = appendMessage(alertMessage, #"Alert Part 1");
otherString = appendMessage(otherString, #"Bleh bleh");
If you really (really, really) want to you can instead "pass the variable" by passing its address (using the & operator) and indirection (using the * operator) inside the block to get/set the value:
void (^appendMessage)(NSMutableString **, NSString *) =
^(NSMutableString **stringPtr, NSString *append)
{
if (!stringPtr) return; // no "variable" passed
NSMutableString *string = *stringPtr; // use indirection to get the value in the passed variable
if (!string)
string = [NSMutableString new];
if (append.length > 0)
{
[string appendString:#"\n"];
[string appendString:append];
}
*stringPtr = string; // use indirection to set the passed variable
};
appendMessage(&alertMessage, #"Alert Part 1"); // pass "variable" by passing its address
appendMessage(&otherString, #"Bleh bleh");
While the above is valid code it is generally not recommended coding practice in Objective-C for simple cases such as yours.
Once you take the address of a variable you need to be concerned over the lifetime of that variable - if you attempt to use the address to access the variable after the variable has been destroyed your program will fail (the dangling pointer problem)
What about __block?
Neither of the above examples use __block anywhere.
When a block references a variable by default it captures the variables value at the time the block is created. The __block attribute changes this to capturing the variable (so its value can be changed by the block) and alters the lifetime of the capture variable if required (so the variable lives at least as long as the capturing block, avoiding the dangling pointer problem).
The __block attribute is not applicable in your situation as you wish to capture different variables based on the call.
HTH
The code, as written, seems to confuse operation on object with object creation.
For clarity's sake, you should either pass in a mutable object to be manipulated or you should define a single __block variable whose value will be set by the block (and you do the logic after to figure out where that value should be stuffed).
Passing in something by reference is inherently dangerous to the point of being an anti-pattern (what happens as soon as you try to refactor the code to be asynchronous? At least in the __block case, the code after the block will see nil).
i.e.:
__block NSMutableString *foo = [sourceString mutableCopy];
doIt(#"new stuff"); // appends to `foo`
whereItShouldReallyGo = foo;

Is it possible to get the result of objc method in dtrace?

I wrote an action that fires when any objc method return (objc:::return).
For now, I need to get the return value. Is it possible?
In summary: no, you can’t get the return value of an Objective-C method in a DTrace probe.
Bill Bumgarner has a post on tracing messages to nil in which he says the following:
Aside: objc_msgSend()‘s return cannot be traced via dtrace at this time. Not surprising given that the function doesn’t actually return — as far as dtrace is concerned, it is nothing but preamble.
The blog post is rather old (January 2008) and it uses the pid provider, not the objc provider. That said, it is still valid as of Mac OS X v10.7.1 and it also applies to the objc provider.
Amusingly, it might seem that it sometimes works but it depends on when DTrace reads the RAX register. Since objc_msgSend() doesn’t return, DTrace ends up using values in RAX that have been stored by code that is not necessarily the return of the method being traced.
Consider the following code:
NSNumber *n = [NSNumber numberWithInt:1234];
printf("n has address %p\n", n);
and the following probe:
objc$target:NSPlaceholderNumber:-initWithInt?:return
{
printf("Returning from -[NSPlaceholderNumber initWithInt:]\n");
printf("\treturn value = 0x%p\n", (void *)arg1);
}
When run using DTrace, I get the following output:
n has address 0x4d283
Returning from -[NSPlaceholderNumber initWithInt:]
return value = 0x4d283
so it seems that the probe was able to capture the return value of -initWithInt:. That’s only luck though, probably caused by a function (e.g. CFNumberCreate() or CFMakeCollectable()) called by -initWithInt: and which ended up placing the expected value in RAX.
Now consider the following code:
char *c = "hello";
NSData *data = [NSData dataWithBytes:c length:strlen(c)];
NSString *s = [[NSString alloc] initWithData:data
encoding:NSASCIIStringEncoding];
printf("s has address %p\n", s);
and the following probe:
objc$target:NSPlaceholderString:-initWithData?encoding?:return
{
printf("Returning from -[NSPlaceholderString initWithData:encoding:]\n");
printf("\treturn value = 0x%p\n", (void *)arg1);
}
When run using DTrace, I get the following output:
s has address 0x7fcd92414ea0
Returning from -[NSPlaceholderString initWithData:encoding:]
return value = 0x600
As you can see, the addresses (i.e., the return values) don’t match. In fact, 0x600 is the value of kCFStringEncodingASCII which is the Core Foundation counterpart of NSASCIIStringEncoding. At some point either the method or a function called by the method moved 0x600 to RAX and that’s the value that DTrace wrongly considered to be the return value.

How do I write to an NSObject from within a C function that doesn't see Obj-C variables?

I'm trying to get some code going that lets me display raw trackpad data from my macbook pro, like the app FingerMgmt. Unfortunately, no one seems to have the source for FingerMgmt. I did find some other source code that kind of works, however. I was able to NSLog the data I wanted to see like this:
int callback(int device, Finger *data, int nFingers, double timestamp, int frame) {
for (int i=0; i<nFingers; i++) {
Finger *f = &data[i];
NSLog(#"Frame %7d: Angle %6.2f, ellipse %6.3f x%6.3f; "
"position (%6.3f,%6.3f) vel (%6.3f,%6.3f) "
"ID %d, state %d [%d %d?] size %6.3f, %6.3f?\n",
f->frame,
f->angle * 90 / atan2(1,0),
f->majorAxis,
f->minorAxis,
f->normalized.pos.x,
f->normalized.pos.y,
f->normalized.vel.x,
f->normalized.vel.y,
f->identifier, f->state, f->foo3, f->foo4,
f->size, f->unk2);
//todo-get data from raw C to obj-C variable
}
return 0;
}
But whenever I try to store any of the data to an Obj-c string or variable, the C code does not see the variable as having been declared. Because of this, I cannot write to any text fields or graphical displays in Obj-C, and I cannot store the data to a variable that Obj-c can access.
Basically, I need a way to write to an Obj-C variable or object from within the callback.
On a side note, I had a very similar problem with an iPhone app a while back, and I ended up fixing it by somehow declaring the app delegate within the C code and writing to or reading from the variable like this-
me.delegate=(id <UIApplicationDelegate,UITabBarControllerDelegate>)[[UIApplication sharedApplication] delegate];//allows access to the delegate within C function
me.delegate.number0=5;//writes to this variable in the delegate
For some reason, I can not seem to adapt this to my current situation. I always get the error that "me" is undeclared.
A Objective-C method can access instance variables because it is automagically passed a hidden parameter with the public name self - any reference to an instance variable, say fred, is translated by the compiler into a field reference, say self->fred (and a similar translation for property references).
For your C function callback to access the fields of any object (or call an object's methods) you need to pass the function a reference to the object. Two simple ways:
Add an argument to the function. Many C callback protocols include a general "user defined" values which is passed around as void *, if you are calling one of these pass your object reference as this value and cast it within the C function back to the correct Objective-C type.
Pass the object via a global (or file static) variable, e.g. static NSSomeType *objectForCallback;. This method works when you're stuck with an existing C callback protocol which doesn't support a user defined value. However it is not thread or re-entrant safe as you are sharing a single static variable.
In both cases make sure the objected is retain'ed if you're not using garbage collection.
In response to comment
Case 1: You will see C functions declared which (a) take a callback function and (b) a user-defined value to pass to that function on every call. For example:
typedef T ...;
T findMatching(T *buffer, // an array of T to search
size_t count, // number of items in array
int (*matcher)(T item, void *user), // user function for match, 1st arg is item, 2nd user-supplied value
void *userValue); // user-supplied value to pass to matcher
If you are faced with C function like this you can pass a (retain'ed if needed) Objective-C object as userValue and cast it back to its Objective-C type inside matcher. For example:
int myMatcher(T item, void *user)
{
NSMutableDictionary *myDictionary = (NSMutableDictionary *)user;
...
}
- (void) someMethod
{
NSMutableDictionary *sharedWithC = ...;
...
T found = findMatching(buffer, count, myMatcher, (void *)sharedWithC);
...
}
Case 2: Objective-C is (a superset of) C. You declare a global just as you would in C. For example (little checking, not thread safe):
static NSMutableDictionary *myGlobalDictionary = nil; // "static" makes the variable only visible to code in the same file
- (void) setupTheSharedDictionary
{
myGlobalDictionary = [[[NSMutableDictionary alloc] init] retain];
}
- (void) releaseTheSharedDictionary
{
if(myGlobalDictionary != nil)
{
[myGlobalDictionary release];
myGlobalDictionary = nil;
}
}
In response to second comment
I'm guessing you are trying to use some third party (Google?) code. That code defines a callback protocol - a C function type. You cannot just redefine that C function type adding an extra argument and expect the third party code to magically cope!
So unless you intend to change the C you can use the second approach - store the reference to Objective-C object in a global. In your case this will be something like:
static MT2AppDelegate *sharedWithCAppDelegateReference;
int callback(...)
{
...
[sharedWithCAppDelegateReference->L1 setStringValue:#"Hellofff"];
...
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
sharedWithCAppDelegateReference = self; // store so C can pick it up
...
MTRegisterContactFrameCallback(dev, callback);
...
}
But remember this is not thread or re-entrant safe - you are effectively passing a function parameter via a global variable. If you need it to be thread/re-entrant safe you need to get a bit more involved.

What does the "*" mean in 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;
}

What does it mean to return an object in a method?

I still cannot understand what does it mean to return an object in a method. What would its value mean?
If I have something like this:
-(ClassName *) methodName: (int) arg {
return arg;
}
I can't understand how an object can be returned through a method as the above. If someone can help me understand.
Thanks.
You would return an object by returning an object. For example, you could ignore the argument:
- (ClassName *)methodName:(int)arg {
return [[[ClassName alloc] init] autorelease];
}
You could turn the int into an object:
- (NSNumber *)methodName:(int)arg {
return [NSNumber numberWithInt:arg];
}
You could use the argument in some calculation to determine some property of the object returned. You could process the argument and return an object indicating the status of the calculation. And so on and so on. There's a practically unlimited range of ways you could return an object from a method. All it requires is that some object be created or accessed and then returned.
The above method returns a pointer to arg which is of type ClassName*.
I assume explaining the question would assume basic knowledge of how functions are called, how passed values are pushed on stack before function call and how return values is returned from a function.
In this specific case your arg variable is part of a class, meaning that it is stored in memory that is part of the object. When you return pointer to it you are pointing to a specific area of memory within the object.
Another option is to return copy of the value. It would mean make a copy and return it.
The difference is that if you return pointer to objects internal variable that object state could be modified from outside.
If you return copy that copy can be modified and the original object will not change.
Not sure if that helps, but you are asking about very basic software development topic which assumes some background knowledge.
Maybe specify what exactly you are looking for?
Think of methods like they are functions in math. In math, sin(180) is equal to 0. sin is the method, 180 is the argument and 0 is the return value of the method. An example of sin in objective-c might go like this:
-(double) sin:(double)angleInDegrees;
{
double sinValue;
//calculate the return value here and store it in sinValue.
//for example, if angleInDegrees is 180, then set sinValue to 0
return sinValue;
}
Returning objects is exactly the same. Look at this example:
-(NSString*) sayHelloTo:(NSString*)name;
{
return [NSString stringWithFormat:#"Hello %#!", name];
}
If I were to write it like a math function, then sayHelloTo(#"Tom") is equal to #"Hello Tom!". The only difference is that #"Hello Tom!" is an NSString object, not a double.