Storing to a variable vs passing directly (does that implicitly create a temp variable?) - objective-c

Model 1
NSString *name = (NSString *)[response valueForKey:#"name"];
[someObject doSomethingWith:name];
Model 2
[someObject doSomethingWith:((NSString *)[response valueForKey:#"name"])];
If i chose model 2 will that save a variable created on the stack Or still an implicit temp variable created behind he scene?
Ignoring loss of readability, is there any benefit in avoiding creating variable that will be used in only place. Instead passing it directly as in model 2?

The code generated by the compiler will be the same, however, there's no variable in the second case. A variable is a high-level programming concept, the resulting assembly code knows about registers and memory only. And in both cases, the return value of the innermost method call needs to be stored somewhere, so either a register or place on the stack will be used for that.
Also, id (what - [NSDictionary valueForKey:] returns) is generic and implicitly compatible with any object pointer type - please, don't cast its return value to NSString *.

Related

When to use alloc init in objective-c

Hey guys I just have a simple objective c question, I have been looking over my companies code base and I have stumbled upon something interesting. When should you use [[alloc] init] and when should you not. Here is a classic example:
Case 1:
NSString *url = nil;
url = #"hi";
Case 2:
NSString *url = [[NSString alloc] init];
url = #"hi";
So when should you use Case 1 and when should you use Case 2? I am hoping someone can settle this for me once and for all, throughout my app development I have been using Case 2 because I thought it was equivalent to calling a "new" in C++ (basically invoking an objects constructor). I am shocked that Case 1 even works, because Case 1 indicates no invokation of a constructor or memory allocation for that object. Case 1 is used everywhere in the code base I am looking at though.
alloc creates storage and does some basic automatic setup, returning an instance of the class. init allows the instance to configure itself as per the logic required for that class. = assigns a different instance to the pointer.
So the first is always correct, the second always incorrect. There's no point creating an instance of an object then throwing it away one line later.
(aside: with ARC you can always skip the = nil as it's implied; in your case you could skip it regardless because of the following assignment)
#"hi" creates an instance of NSString. It does the allocation and initialization. Therefore, in case 2, you are pointlessly allocating memory and then reassigning the "url" pointer to a new piece of memory.
You have to remember that "url" is a pointer. Just like in C or C++, when you use the "=" operator you are reassigning where it is pointing, you are not affecting the memory it used to be pointing at. In C, if you want to change the value stored at the newly allocated memory, you would have to use the dereference operator.
alloc creates an object. So you use it when you want to create an instance of a class. In this case, you do not want to create an object, because you're going to assign the existing object #"hi" to the variable. So you would never write Case 2, as it creates an object and immediately discards it for another object.

Are pointers to arguments in Objective C methods are const by default?

There are methods in Cocoa classes that accept an address of a pointer. Most commonly the argument is address of future NSError * object in CoreData validation methods (among others). This way it is possible to put custom or owned object into the place of the address that given argument points to.
My question is: why can't we do that with simple pointer arguments? E.g. let's say I have a method:
- (void)addObject:(id)someObject toArray:(NSMutableArray *)array;
I can easily pass the mutable array as second argument, call addObject: on it and after the method call the array will be modified. Why is this not done with NSError * objects? Are pointers passed to methods are defined as const by default? Is this to avoid accessing NULL?
Why is this not done with NSError * objects?
Because there's no such thing as an NSMutableError. Your example works because you can modify the contents of the array without modifying the pointer to the array itself. However, since NSError instances are immutable, you cannot modify an NSError. As such, you must necessarily create a new error object. And if you want to return that error object along with some other piece of data, at least one of those must be done via an out-parameter (such as an NSError **).
Are pointers passed to methods are defined as const by default?
Nope. Inside that method you're welcome to do this:
- (void)addObject:(id)someObject toArray:(NSMutableArray *)array {
someObject = somethingElse;
[array addObject:someObject];
}
What's important to remember here is that you're only changing a pointer in a slot in memory. The memory slot corresponding to someObject is just a space on the stack, and you're changing the contents of that space to have a value that points to a different allocated object than the one you were given.
Is this to avoid accessing NULL?
Any NULL protection you need must be done yourself.
It's because the NSError class does not define any way to modify instances after creation. The pointer itself is mutable, but an NSError is not.
They are all plain C pointers. They are not const unless you make them const. Const pointers are not a good thing to use in most situations in objective-C, or even often plain C. Const pointers are a subtle concept, and the complexities of the meaning and syntax don't mesh well with the Objective-C style of programming. Forgetting they exist is likely a good first approximation.
Example: NSArray and NSMutableArray - we would not need an NSArray class if const worked 'correctly' - but it can't due to the design of C.
** - For NSError, etc., the idea is to create an NSError, not alter the one you have passed in. In other words, you need a pointer to a pointer to be able to create an instance (i.e. change the actual object).

What is difference between dynamic binding Vs dynamic typing in Objective C

I am having hard time to understand what is difference between dynamic binding Vs dynamic typing in Objective C. Can someone explain this ?
Dynamic typing in Objective-C means that the class of an object of type id is unknown at compile time, and instead is discovered at runtime when a message is sent to the object. For example, in the following code, the class of foo isn't known until we attempt to send the message componentsSeparatedByString:.
id foo = #"One Two Three";
NSArray *a = [foo componentsSeparatedByString:#" "];
If instead of using the id data type we had done the following...
NSString *foo = #"One Two Three";
...then we'd be using static typing rather than dynamic typing.
Dynamic binding means that the compiler doesn't know which method implementation will be selected; instead the method implementation is looked up at runtime when the message is sent. It basically helps us with Polymorphism. So
[foo description]
results in invoking a different method implementation if, for example, foo is an instance of NSArray rather than an instance of NSString.
with dynamic typing you can have a variable of type id that can store any type of object. with dynamic binding you can do this: id obj; [obj doWhatever]; and as long as obj is of a type that implements -(void)doWhatever it will work.
From Apple Documentation
Dynamic typing
A variable is dynamically typed when the type of the object it points to is not checked at compile time. Objective-C uses the id data type to represent a variable that is an object without specifying what sort of object it is. This is referred to as dynamic typing.
Dynamic typing contrasts with static typing, in which the system explicitly identifies the class to which an object belongs at compile time. Static type checking at compile time may ensure stricter data integrity, but in exchange for that integrity, dynamic typing gives your program much greater flexibility. And through object introspection (for example, asking a dynamically typed, anonymous object what its class is), you can still verify the type of an object at runtime and thus validate its suitability for a particular operation.
The following example illustrates dynamic typing using a heterogeneous collection of objects:
NSArray *anArray = [NSArray arrayWithObjects:#"A string", [NSDecimalNumber zero], [NSDate date], nil];
NSInteger index;
for (index = 0; index < 3; index++) {
id anObject = [anArray objectAtIndex:index];
NSLog(#"Object at index %d is %#", index, [anObject description]);
}
The object pointed to by the variable at runtime must be able to respond to whatever messages you send to it; otherwise, your program throws an exception. The actual implementation of the method invoked is determined using dynamic binding.
Dynamic binding
Dynamic binding is determining the method to invoke at runtime instead of at compile time. Dynamic binding is also referred to as late binding. In Objective-C, all methods are resolved dynamically at runtime. The exact code executed is determined by both the method name (the selector) and the receiving object.
Dynamic binding enables polymorphism. For example, consider a collection of objects including Dog, Athlete, and ComputerSimulation. Each object has its own implementation of a run method. In the following code fragment, the actual code that should be executed by the expression [anObject run] is determined at runtime. The runtime system uses the selector for the method run to identify the appropriate method in whatever the class of anObject turns out to be.
NSArray *anArray = [NSArray arrayWithObjects:aDog, anAthlete, aComputerSimulation, nil];
id anObject = [anArray objectAtIndex:(random()/pow(2, 31)*3)];
[anObject run];
If you are familiar with Javascript, dynamic typing in objective C is pretty much similar to what 'var' is in Javascript, where the actual type of this variable will be figured out at run-time and once it's assigned. It can be reused and retyped as many times as you like which makes it risky to use if you don't know the type of the object being held at the time of the execution as you as it could through 'unrecognized selector' run time exceptions. In Objective-C, all objects are of type id and therefore a variable of type id can be used for dynamic typing.
Dynamic Binding on objects is the 'polymorphic' behavior where the right method is called based on the type of object it's being called on at run time.
I hope that helps

How do you declare instance of the class in Objective C?

Let's imagine I have Fraction class. So, the correct way to create instance of it is:
Fraction *myFraction;
or
myFraction = Fraction;
or
myFraction = [Fraction new];
or something else?
In the book i'm studying the correct one is first, but it looks unreasonable to me. Why do we have to create a pointer for it? Why don't we make the real instance?
That first expression means - give me a pointer to the new instance of Fraction class, doesn't it?
The first declares a variable named myFraction of type Fraction *, but doesn't create anything, nor initialize myFraction. The second isn't valid. The third creates a new Fraction and assigns it to a previously declared variable named myFraction. Often in Objective-C, you'll declare and initialize a variable in a single statement:
Fraction *myFraction = [[Fraction alloc] init];
As for whether to use new or alloc followed by init, it's largely a matter of taste.
Variables for storing objects are pointers in part because Objective-C inherited C's call-by-value semantics. When one variable is assigned to another (such as when passing it to a function), the value will be copied. At best, this is inefficient for immutable objects. At worst, it leads to incorrect behavior. Pointers are a way around call-by-value and the copy-on-assign semantics: the value of a variable with pointer type is just the pointer. It can be copied without touching the target object. The cost for this is you need some form of memory management.
It would be a good idea to read Kernihan and Ritchie's "The C Programming Language" so you can get an idea about how variables are declared.
There are two modes of allocation in C and Obj-C and C++: manual and automatic.
Integers and floats and characters and such are generally automatically declared. They are created when the declaration passes (i.e. int i), and deleted when the scope they were created in goes away, i.e. when you exit the block in which they were declared. They're called automatics. (it's also possible to declare them "static" but for the purposes of this discussion regarding allocation, these are the same)
Objects are too complicated to pass around to functions, as function parameters are "pass by value", meaning that the parameter gets a copy of the value being passed in, instead of the variable itself. It'd take a huge amount of time to copy a whole object all the time.
For this reason, you want to just tell the various functions where they can find the object. Instead of handing off a copy of the object, you hand off a copy of the address of the object. The address is stored in an automatic with a type of pointer. (This is really just an integer, but it's size is dictated by the hardware and OS, so it needs to be a special type.)
The declaration Fraction *myFraction; means "myFraction is a pointer, and just so you know, it's going to point to a Fraction later."
This will automatically allocate the pointer, but not the whole Fraction. For that to happen, you must call alloc and init.
The big reason why you have this two step process is that since we typically want objects to stick around for a while, we don't want the system automatically killing them at the end of a function. We need them to persist. We create places to hang the object in our functions, but those hangers go away when they aren't needed. We don't want them taking the object with them.
Ultimately, you might make declarations like this:
Fraction *myFraction = [[Fraction alloc] initWithNumerator: 2 Denominator: 3];
which says: "Make me a Fraction, and set it to be 2/3, and then put the address of that Fraction into 'myFraction'."
Why do we have to create a pointer for it? Why don't we make the real instance?
In Objective-C, every object is pointer type. So, you need to use either new or alloc/init.
Fraction *myFraction = [ Fraction new ] ;
or
Fraction *myFraction = [ [Fraction alloc] init ] ;
And myFraction needs to be released.
That first expression means - give me a pointer to the new instance of Fraction class, doesn't it?
No, you are just declaring a pointer of type Fraction. And the second statement is not even valid.

Arguments by reference in Objective-C

I'm trying to pass an NSString by reference but it doesn't work.
This is the function:
+(void)fileName:(NSString *) file
{
file = #"folder_b";
}
and this is the call:
NSString *file;
[function fileName:file];
nslog(#"%#",file); // and there is nothing in the string....
What I must do to pass my string by reference?
If you want to return a value, then return a value. Pass by reference in Cocoa/iOS is largely limited to NSError**.
Given:
+(void)fileName:(NSString *) file
Then do:
+(NSString *) fileName;
And be done with it.
If you need to return more than one value at a time, that begs for a structure or, more often, a class.
In Objective-C, pass by reference smells like you are doing it wrong.
Pass by reference in Objective-C is reserved largely for returning NSError* information about a recoverable failure, where the return value of the method itself indicates whether or not the requested task succeeded or failed (you can pass NULL as the NSError** argument to allow the method to optimize away creating said error metadata).
Pass by references is also used to retrieve interior state of objects where the return value is effectively a multi-value. I.e. methods from AppKit like the following. In these cases, the pass-by-reference arguments are typically either optional or are acting as secondary return values.
They are used quite sparingly across the API. There is certainly use for pass by reference, but -- as said above -- doing so should be quite rare and rarer still in application code. In many cases -- and in some of the cases below, potentially -- a better pattern would be to create a class that can encapsulate the state and then return an instance of said class instead of pass by reference.
NSWorkspace.h:- (BOOL)getInfoForFile:(NSString *)fullPath application:(NSString **)appName type:(NSString **)type;
NSTextView.h:- (void)smartInsertForString:(NSString *)pasteString replacingRange:(NSRange)charRangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString;
NSAttributedString.h:- (BOOL)readFromURL:(NSURL *)url options:(NSDictionary *)options documentAttributes:(NSDictionary **)dict;
NSNib.h:- (BOOL)instantiateWithOwner:(id)owner topLevelObjects:(NSArray **)topLevelObjects NS_AVAILABLE_MAC(10_8);
NSSpellChecker.h:- (NSRange)checkGrammarOfString:(NSString *)stringToCheck startingAt:(NSInteger)startingOffset language:(NSString *)language wrap:(BOOL)wrapFlag inSpellDocumentWithTag:(NSInteger)tag details:(NSArray **)details NS_AVAILABLE_MAC(10_5);
I believe you're looking for:
+ (void)fileName:(NSString **)file
{
*file = #"folder_b";
}
What's really done here is we're working with a pointer to a pointer to an object. Check C (yup, just plain C) guides for "pointer dereference" for further info.
(...But as has been pointed out repeatedly, in this particular example, there's no reason to pass by reference at all: just return a value.)
Passing a pointer to your object is the Objective C (and C) way of passing by reference.
I agree with 'bbum' that a perceived need to pass by reference is a signal to think about what you are doing; however, it is by no means the case that there are not legitimate reasons to pass by reference.
You should not create classes willy-nilly every time you have a function or method that needs to return more than one value. Consider why you are returning more than one value and if it makes sense to create a class for that then do so. Otherwise, just pass in pointers.
-Just my 2 cents
Try this
+(void)filename:(NSString **)file {
*file=#"folder_b";
}
and send the file as &file like:
NSString *file;
[function fileName:&file];
nslog(#"%#",file);
hope this will work.
I suspect this is because NSString is immutable. Have you tried NSMutableString?