I would like to ask all the Cocoa veterans out there - is there any difference in performance between using mutable versus immutable objects in cases like:
NSString's stringByAppendingString: versus NSMutableString's appendString:
NSArray's arrayByAddingObject: versus NSMutableArray's addObject:
...
Thank you and happy coding!
This question is hard to answer : NSArray and NSString aren't actual implementations, they are class-clusters and so are NSMutableArray and NSMutableString. The true implementations underneath can't be determined and thus performances would be hard to compare.
You probably won't find a definite answer to that one.
But what I would guess is : stringByAppendingString and arrayByAddingObject create new objects which contains the modifications, ie copy the current items to a new place in memory, NSMutableArray and NSMutableString should have better performances because they are built to prevent copying when possible (not actually true because NSMutableArray might recopy memory when elements are added but not every time).
I think you should trust the CoreFoundation coders on this one : you wan't to mutate objects ? Use the mutables one.
Related
I'm new into Obj-C.
I would like to know will there be any problems if I assigning NSMutableArray to NSArray as like example code below:
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:#"item1", #"item2", nil];
NSArray *array = mutableArray;
I know that if i use [mutableArray copy] it will duplicate the array as new set. My question is will my approach conflict with any guidance or will have any problems?
Thanks.
Both pointers will refer to the same object. The nature and behavior of that object will remain the same. It is not aware nor affected by which pointers refer to it.
If the array is mutated, those mutations will be observable regardless of which pointer you use to message or examine the array.
The compiler will complain if methods present in NSMutableArray but not NSArray are sent via the array pointer. However, if you ignore the compiler's complaints, the methods will still work as normal. The static types of the pointers is only significant at compile time. They are not represented in the compiled program (except, possibly, in debugging information, but that doesn't affect runtime behavior).
The catch is this:
if mutableArray changed somehow, and the array still think of it self immutable.
Then, things might get out of control.
Other than this, I don't see much problem here...
Your array will stay mutable, but compiler will think that it is immutable. So it won't allow you to use methods specific for NSMutableArray without typecasting.
Is it appreciably more efficient to create an NSMutableDictionary using a constructor
[NSMutableDictionary dictionaryWithObjectsAndKeys:#"object1", #"key1", #2, #"key2", nil];
than taking the mutable copy of a literal
[#{#"key1":#"object1", #"key2":#2} mutableCopy];
As Jeremy said; measure, measure, measure.... then optimize if you have a real problem.
Without looking at the source, I can think of possible reasons why either might be faster and that answer may change depending on # of entries.
The real question, though, is why do you have an app architecture where it matters? It is quite rare to have an application that is creating so many mutable dictionaries (or dictionaries so large) that it is a performance issue.
I know the basics of memory management, but not the internals of how iOS handles the different datatypes. Something always nags me that it's best to use an NSData vs NSMutableData or NSString rather than an NSMutableString. Is there really any performance difference unless the code's going to be running in a 10k loop or am I wasting my time?
Use the mutable types where you want to be able to change the contents in place. Use the immutable types otherwise.
In some cases you don't have a choice - such as the data object that holds the returned data from an NSURLRequest: Using a mutable data object is a lot easier than creating a lot of immutable data types and joining them up at the end.
After that, run your code through the profiler and see whether you should do anything differently. i.e. whether the overhead of creating new immutable types to hold objects is more efficient than using a mutable type. Anything else is a premature optimisation.
Like you said its only worth if you call use Mutable many times. But if you call it only a few times this isnt any Problem.
You should think about alternatives, e.g. in a larger TableViews cellForRowAtIndexPath: method. Use [NSString stringWithFormat:#"%#%#", fristString, secondString], Instead of *foo = [[NSMutableString alloc] init] and [foo append:firstString] and so on.
I want to ask a question about the objective C. When I study the library from the apple developer website. I always see that there are some subclass called "mutable". For example, the NSArray and NSMutableArray. What does it mean about this word. Are there some special meaning? Can anyone tell me? Thank you.
It means you can change its values. If you look at the NSMutableArray docs, you'll see it defines extra methods like -addObject:. NSArray by itself doesn't have these (and can thus be more efficient / take less memory in implementation).
Also note, if you call [myMutableArray copy] you'll get a non-mutable copy of it (which you must later release0. And similarly there's -mutableCopy.
Mutable means you can change it. Look at the difference between addObject in NSMutableArray and arrayByAddingObject in NSArray.
From the Objective-C Beginner's Guide it states the answer to your specific question:
There are two kinds of arrays (and of
usually most data oriented Foundation
classes) NSArray and NSMutableArray.
As the name suggests, Mutable is
changable, NSArray then is not. This
means you can make an NSArray but once
you have you can't change the length.
This tech note also implies you can change the length of a mutable array after the array has been created.
In general mutability stems from these meanings. This will help provide a more broad understanding for when you encounter it elsewhere.
Why does Objective C provide both class NSString and subclass NSMutableString rather than just provide NSMutableString? Isn't a NSString equivalent to "const NSMutableString"?
In C++, you have only one string class, std::string, and if you want a constant you declare a const std:string.
I'm interested in knowing why I shouldn't just use NSMutableString everywhere and never bother with NSString? There must be a reason, or the language designers wouldn't provide both. maybe it takes up less storage or something?
It is very possible, and even likely, that there are optimizations in place that are only allowed when strings are immutable.
In fact running
NSString *A = #"Bob";
NSString *B = #"Bob";
in the debugger immediately shows that they are both pointers to the same string. In fact
NSString *C = [NSString stringWithString:#"Bob"];
NSString *D = [A copy];
both point to the same memory address as well. Meanwhile
NSString *E = [NSMutableString stringWithString:#"Bob"];
points to a different string.
So yes, using NSStrings are more efficient in some cases. And in general cocoa lends itself to returning a new copy of a string rather than an edited one. However, I can't really argue that you shouldn't use a mutable string everywhere, but it does seem to go against the general guidelines for the framework.
In my own work I tend to only use mutable variants where I need to edit things directly. It's just a little backwards from the C/C++ style of everything mutable unless you need a const, everything is const unless you need mutability.
The reason for both classes is the same reason that you sometimes use a std::string and sometimes use a const std::string. However, unlike C++, Objective-C doesn't have const methods, so they instead separate const- from non-const- methods into two different classes. This is also seen in many of the core classes, such as NSArray (NSMutableArray), NSDictionary (NSMutableDictionary), etc.
I would say the general rule is "don't use a class whose purpose is to provide functionality you don't need". If you need to change the contents of a string directly, use NSMutableString. If not, use NSString. In terms of size and how much heap space they take up, the classes themselves should be pretty similar.
I think the usage of an immutable string is a hint for the compiler which can perform optimizations by knowning it won't change.