Why is `&` (ampersand) put in front of some method parameters? - iphone

I'ver wondered, why is it that in front of an NSError, such as below, do we put: &error and not error?
E.g.
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
Hope you can explain, also is this always the way or only in certain situations this is needed? Thanks.

You need to take the address of error because the function needs to modify it. error is passed by pointer, so you need the "take address" operator & for it.
C and Objective-C pass parameters by value. If you pass error without an ampersand and the method that you call modifies it, your function that made the call would not see any changes, because the method would operate on its local copy of NSError*.
You know that you need an ampersand in front of the corresponding parameter if you look at the signature of the method and see ** there:
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error
// ^ one ^^ two

The error parameter's type is (NSError **), that is a pointer to a pointer to an NSError. The error variable that you use as the argument is probably declared as NSError *, so in order to get the types to match properly, you have to use the address of operator to get a pointer to a pointer (&error). The reason the method needs a pointer to a pointer in the first place is so that it can modify the value of error and have that new value be available to you, the caller of the method.

Essentially, the root of the issue is a hack for wanting to return a second (optional) object.
How can we do this, as we can only return one thing? Well, we could return some sort of (return_value, error) tuple, but that's a bit unwieldy. We can have as many parameters as we like though, can we do something with those...
So, methods/functions can't modify their parameters (to be precise, they operate with a copy, so any modifications they make are local). That is to say (concurrency issues aside) the value of fetchRequest before the message in your question will be equal to the value of fetchRequest afterwards. Note the object pointed to by fetchRequest might change, but the value of fetchRequest itself won't.
This puts us in a bit of a bind. Except, wait, we know we can happily take the value of a parameter and modify what it points to! If you look at the declaration for executeFetchRequest:error: you'll see it takes an NSError**. That's "a pointer to a pointer to an NSError". So, we can initialise an empty/dangling NSError*, find the address of it (with the unary & operator), and pass that in. The method can then assign to the NSError* pointed to by this.
Voila, we effectively have optional additional return values.

Related

What happens if you pass nil at runtime to a parameter that shouldn't accept that?

Say I have a method that takes a CLLocationCoordinate2D. I can't pass nil directly to that in code; the compiler complains. However, the following compiles. So what happens at runtime?
CLLocation* loc = nil;
[self passMeCoordinates:loc.coordinate];
This is an interesting question. I assume your earlier code was:
[self passMeCoordinates:nil];
The compiler complains about this because CLLocationCoordinate2D is not an object. It's a C-style struct. So, you can't pass an object/pointer (nil) where a struct is expected. (They're not the same size, etc.)
If I slightly paraphrase your code to:
CLLocation* loc = nil;
CLLocationCoordinate2D coord = loc.coordinate;
[self passMeCoordinates:coord];
The question comes down to "what value does coord have". As you may know, the rule in Objective-C is that if you send a message to nil (as we do here -- loc.coordinate is equivalent to [loc coordinate]), then you get back 0. But what if we're expecting a struct? As I just mentioned, it's not the same size as an integer. Well, it turns out that the result depends on what compiler you're using:
LLVM 3.0+ (Xcode 4.2+): returns all zeros, so it's equivalent to a coordinate of (0,0): Can I rely on nil UIView returning CGRectZero for its frame?
LLVM Earlier/GCC: a struct can be filled with garbage/undefined contents, so it could be anything.
Loc.coordinate is a structure so you cannot pass nil for that.
And method that return C structure are not safe to be call on nil.
So your warning is not about passing nil as argument.
As of your question about nil as argument. Well it depends on the method, some handle nil gracefully others don't. Refer to the documentation of those method it's usually said if you can or cannot pass nil as argument.
As others have pointed out, you're dealing with a struct property of your location object, and therefore nil will be problematic. You should only be using nil with objects.
But more generally, you should never assume that any method will accept nil as a parameter. It all varies from method to method. For the built-in classes, it will generally specify in the documentation when a nil parameter is acceptable. If it doesn't say that nil is permissible, it's wise to assume that it's not.
Whether your own code accepts a nil parameter is entirely dependent upon what you do with that parameter and if you're doing anything that requires it to not be nil, whether your code is checking for non-nil values and handling appropriately, etc.
As a completely random example, if you have a method that does:
NSMutableArray *array = [NSMutableArray array];
[array addObject:text];
This will generate a NSInvalidArgumentException exception if text is nil.
Bottom line, it all varies, method to method. Refer to the documentation for the methods in question to see if nil is permissible or not.
The one general exception to the "don't use nil unless the documentation says you can" rule is that when sending messages to a nil object (i.e. invoking a method on an object that is nil). That is permissible (but obviously does nothing). As the documentation says:
In Objective-C, you can often send a message to nil with no ill effects. Return values from messages sent to nil are guaranteed to work as long as what is returned is typed as an object.
At runtime nil will get passed to your method. The compiler does not do runtime checking , it only does compile time type checking.

Passing objects to methods?

I have corrected something that was confusing me in V2 but am still a little curious as to what V1 is doing. Looking at V1 now am I right in thinking that line is being passed by value (so essentially what I have is a local copy of line). Scanner then scans its data into the address of that local copy, the local copy is destroyed when the method exits and the external variable line is still nil?
On V2, I am passing the address of line and then scanning data into that address, is this using passing by reference, just not sure of the terminology?
// V1
NSString *line = nil;
[self scanUsing:scanner into:line];
NSLog(#"AFTER_: %#", line);
- (void)scanUsing:(NSScanner *)scanner into:(NSString *)line {
[scanner scanUpToString:#"\n" intoString:&line];
NSLog(#"INSIDE: %#", line);
}
.
// V2
NSString *line = nil;
[self scanUsing:scanner into:&line];
NSLog(#"AFTER_: %#", line);
- (void)scanUsing:(NSScanner *)scanner into:(NSString **)line {
[scanner scanUpToString:#"\n" intoString:line];
NSLog(#"INSIDE: %#", *line);
}
V1
You are passing a copy of the pointer. It points to the same memory region, so what you see is the same value. You are passing the object then, by value. You can change the content, but not create a new object, since that pointer wont exist when the method finishes.
V2
Definition of reference is different (its a C++ type) But yeah, lets say that it behaves more or less the same. In V2 a new object can be allocated inside the method, and therefore, you can change the memory region that is being pointed by it.
So:
V1, passing by value. You pass the pointer, and can change the content of the object pointed by the pointer.
V2, passing by reference. You pass a pointer to a pointer, and therefore you can alloc memory, and so change the pointer address as well.
Since this is not C++, you can't call it pass-by-reference. You can, however, call it pass-by-pointer. (Which is still by value, but you're passing a pointer by value.)
Apart from grammar nazi: the first version modifies only the local copy of line (i. e. the one inside the function); the one you actually passed in stays unchanged.
In V1, you're changing the value of the line local parameter, which only exists in the scope of the method, you're not changing your global line variable.
In V2, you effectively pass the global line pointer by reference, which allows you to change its value...
In the first example, you are passing a reference to an object.
In the second example, you are passing a reference to a reference of an object.
If you log the line-object in the first example, you would see difference, while in the second you would see the object you have set inside the method.
this is often used for NSError, where you have a basic return type, but you also want to notify if there was an error. You pass then a pointer to your error variable, and they pass it the reference to the NSError object. I hope this made at least a little sense to you :)

CoreData Object typing won't work

Can someone explain to me why this doesn't work:
CoreDataClass *classObject = (CoreDataClass *)[some method that returns a dictionary with exact KVC pairs that match CoreDataClass];
NSString *myString = classObject.stringProperty;
But this does:
CoreDataClass *classObject = (CoreDataClass *)[some method that returns a dictionary with exact KVC pairs that match CoreDataClass];
NSString *myString = [classObject valueForKey:#"stringProperty"];
EDIT:
What's the easiest way to cast the dictionary as my NSManagedObjectClass CoreDataClass so I can access properties directly?
It doesn't work since KVC compliance is not at all what defines classes or makes them castable - the class hierarchy exists for a reason, and just ensuring adherence to certain methods doesn't magically make something an instance of a completely different class. Keep in mind that the dot-accessor syntax is just sugar for a method send, so these two are equivalent:
classObject.stringProperty
[classObject stringProperty]
...and the latter obviously isn't valid for instances of NSDictionary (i.e. [[NSDictionary class] instancesRespondToSelector:#selector(stringProperty)] is NO).
Your latter example works because of the very premise of your question: if something is KVC-compliant for the key stringProperty, and you ask it for a value for that key, then obviously you get something back. Furthermore, both NSDictionary and CoreDataClass respond to the selector -valueForKey:, so the message send actually works at runtime.
The best way to get the two across isn't a "cast" at all - it's a complete conversion, at the property level, of the data involved. You might consider creating a custom -initWith... method on CoreDataClass that lets you instantiate its properties from a dictionary, or finding a way to get your method to return an actual instance of CoreDataClass instead of an NSDictionary.
Note that this solution may differ from the "easiest" way to get the data across, which is effectively to keep doing what you're doing and use -valueForKey: (though preferably without the cast, which is misleading).
Casting objects only appears to work (in the sense that you won't get type-checking errors) because it's a hint to the compiler, but it doesn't actually change anything about what the pointer points to, so you are still pointing to an NSDictionary. This is because, at the end of the day, you are essentially casting a pointer to a pointer, but telling Xcode that you are allowed to send a different set of selectors to it.
For NSManagedObjects, creation from a dictionary depends on a few things, but the recommended way is to make a class method on your custom class which will use NSEntityDescription and you NSManagedObjectContext, and sets the properties from the dictionary to the object:
+(CoreDataClass *) coreDataObjectWithDictionary:(NSDictionary *) spec {
CoreDataClass *myInstance = [NSEntityDescription insertNewObjectForEntityForName: #"CoreDataClass" inManagedObjectContext: [myMOCProvider sharedMOC];
myInstance.someProp = [spec valueForKey:#"someProp"];
}

Can someone tell me the difference between the call in IOS

I have a method called Display. Can somebody explain me the difference of calling the same method in the following two ways.
[self Display];
[self performselector:#selector(Display)]
- (void)Display {
NSlog(#"Data");
}
both are basically the same with one minute difference.. #selector gives a name to your method which you can pass around as an attribute to other objects or in other function calls.
Like if you want to send a message to other object and you want to send display as an attribute then you will have to give it a name using #selector and thus you can send it.. its a pretty vague concept.. hope this helps.
and to quote apple documents...
"However, the performSelector: method allows you to send messages that
aren’t determined until runtime. A variable selector can be passed as
the argument:
SEL myMethod = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector:myMethod];
The aSelector argument should identify a method that takes no
arguments. For methods that return anything other than an object, use
NSInvocation."
[self Display] is shorter and easier to read, write and comprehend.
[self performSelector:#selector(Display)] makes it possible to execute arbitrary selectors. If you save the selector in a variable, then you can execute it later on without knowing the method you invoke. It is therefore more flexible. Even better: you can pass selectors and objects to other objects and let them invoke it for you when necessary. An example why you want to use this is the NSUndoManager which simple invokes a selector to undo an action if the user executes the Undo command.
I do not think that there is a big difference between examples you provided, but perform selector is very useful when you for instance wanna move execution of your method to the background thread.
[self Display]; is a call to a known method on a known object.
It's easy to give it some params if your want : [self DisplayWithParam1:(NSString*)aString param2:(int)aNumber param3:(NSDictionary*)aDict
[self performselector:#selector(Display)] is a call that allows you to call a possibly not known method on a possibly not known object type.
Let's imagine you have many kind of classes that all respond to a given protocol that require to have the Display method implemented. You put some objects of thoses different classes in an NSMutableArray. When parsing the array later, you will get id typed objects.
So calling[myArrayObject Display]; will work at runtime but will generate a warning at compile time as id does not support any method of course, even if you know that this object supports the method.
To prevent thoses warning, call [myArrayObject performselector:#selector(Display)];.
The problem with that call is that is harder to pass some parameters.
performSelector:withObject:withObject:
Sends a message to the receiver with two objects as arguments.
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
Parameters
aSelector
A selector identifying the message to send. If aSelector is NULL, an NSInvalidArgumentException is raised.
anObject
An object that is the first argument of the message.
anotherObject
An object that is the second argument of the message
Return Value
An object that is the result of the message.
Discussion
This method is the same as performSelector: except that you can supply two arguments for aSelector. aSelector should identify a method that can take two arguments of type id. For methods with other argument types and return values, use NSInvocation.
Availability
Available in Mac OS X v10.0 and later.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html
The #select call is faster. Generally the uglier (and less dynamic) the code you have in Objective-C, the faster it runs. Here, the selector call bypasses the usual call to objc_msgSend().
I wouldn't recommend writing code like this if you can avoid it. Selectors are somewhat common in Cocoa, but if you're using it for a speedup it's really not worth it. objc_msgSend() is highly optimized and very fast.

Printing arguments sent to forwardInvocation: subclass of NSProxy

I want to intercept messages sent to a proxy object by just printing the selector and arguments. Even if the proxy does not implement them and does not have a target object. Please help. I have looked at several options and Apple docs but they assume that you already know the target object. I want to do this cleanly without memory issues.
#implementation MyProxy
-(void)forwardInvocation:(NSInvocation*)anInvocation
{
// at this point I would
//like to fetch the arguments and put on an array
NSMutableArray *myArgs = .....;
NSLog(#"Invoking selector %#", theSelector);
NSLog (myArgs); // this should print me the list of arguments to the method
}
#end
// e.g
MyProxy *proxy = [[MyProxy alloc] init];
[proxy SendMeAnyThing: #"hello"]; // this should print me arguments
or [proxy add: 12 to: 89 sub: 89]; // should print the arguments
Thanks thanks
The arguments are of just about any C type, including Objective-C types, that may be passed to the method. Thus, they can't be represented in an array.
Note that invoking a method that is not declared anywhere doesn't make any sense. Quite specifically, the compiler has no idea how to encode the arguments at the call site to make a valid C function call (a method call is really just a C function call to objc_msgSend() or a variant). So, to answer your "any method, even if it doesn't exist" question; no, you can't do that.
You can, however, effectively eliminate all compiler warnings. If you eliminate all compiler warnings -- all "method foo:bar: has can't be found" type warnings -- then that means the compiler does have enough information and you can do whatever the heck you want with a proxy.
Furthermore (as I read more into your question), there is no need to implement any method on the proxy. A proxy can quite happily forward-into-NSInvocation any method call. Written correctly, you can have a proxy stand in for any object without issue.
What you need to do is enumerate the arguments using the API of NSInvocation, sussing out the types and then decoding each argument accordingly and printing appropriately.
You can grab the number of arguments by invoking numberOfArguments on the method signature of the NSInvocation instance (the signature can be had via the methodSignature method).
Then, loop through the arguments and call getArgumentTypeAtIndex: on the method signature to get the type. You would then most likely write a switch() statement on the type encoding to then call getArgument:atIndex: and decode appropriately based on type.
Note that argument 0 is self and argument 1 is _cmd; the SEL of the method that was invoked.