What is the purpose of having both NSMutableString and NSString? - objective-c

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.

Related

What is CFArray and difference between CFArray vs NSArray

this might be a duplicate question but i have go through the so many blogs and documents , but still i can't figure out what is CFArray.
As performance wise which one is best and when to use and which situation.
Please throw a light in this topic.
A CFArray is an NSArray and vice-versa.
Core Foundation (where the CF comes from in the name) is Apple's C-oriented collection of functions and data types. Cocoa (the NS comes from NextStep, Cocoa's ancestor) is Apple's Objective-C framework.
Certain types in the two two frameworks are toll-free bridged - that means the data structure is shared between the two frameworks, Core Foundation operates on it using C-style function calls, Cocoa operates on it using Objective-C style method calls.
Sometimes one framework might provide operations the other does not, but in general you use Cocoa from Objective-C and Core Foundation from C when considering a toll-free bridge type.
Cocoa objects are automatically managed by ARC, a big advantage. In Core Foundation you use manual memory management. Objective-C has a number of "bridge" casts which inform the compiler when you are transferring responsibility for memory management between ARC and manual Core Foundation calls.
Given they are the same data-structure any performance difference is down to the such things as an extra call-level overhead if a Cocoa method just calls a Core Foundation one, etc. In general you should not be concerned about this unless you've identified a performance issue.
HTH
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, arraySize, &kCFTypeArrayCallBacks);
for (int i=0;i<arraySize;i++) {
CFStringRef string = CFBridgingRetain(#"This is an awesome string"); // CFStringCreateWithCString(kCFAllocatorDefault, "This is an awesome string", kCFStringEncodingUTF8);
CFArrayAppendValue(array, string);
CFRelease(string);
}
CFIndex count = CFArrayGetCount(array);
for (int i=0;i<count;i++) {
CFStringRef string = CFArrayGetValueAtIndex(array, i);
}
CFRelease(array);
let’s go over the CFArray code. In the CoreFoundation version, we first create a mutable CFArray (CFMutableArray) via the CFArrayCreateMutable() function call, providing the allocator, array size and the callback function. We then setup a very conventional-looking for loop, iterating over the array the number of time indicated by arraySize (this number will change in our tests). A string is then created and appended to the array and released. You might notice that we actually create and Objective-C string literal and transfer the ownership over to CoreFoundation via CFBridgingRetain(). This means that ARC will no longer take care of releasing the string for us and we must do so explicitly with CFRelease(). An alternative to this is to use create a string with a CoreFoundation call to CFStringCreateWithCString() (which is commented out), but this method is much slower and we are interested in comparing the array performance, not string allocation performance. The second portion of the code will get the array count, setup another loop and get the value at index with every iteration. We don’t actually do anything with the string.
NSMutableArray *container = [[NSMutableArray alloc] initWithCapacity:arraySize];
for (int i=0;i<arraySize;i++) {
NSString *string = #"This is an awesome string";
[container addObject:string];
}
NSUInteger count = [container count];
for (int i=0;i<count;i++) { // (NSString *string in container) {
NSString *string = container[i];
}
The Objective-C Foundation counterpart is very similar in nature but removes the need for CFRelease() as we are under ARC. Most of this code is pretty self-explanatory so we won’t go through it in detail. One thing to point out, however, is that with Foundation you have the option of using Fast Enumeration, which will actually give you some performance gains, as we’ll see later on. This is commented out beside the conventional for loop.
It's important to note, that while the other answers are correct in the common case, it is possible to create CFArray variants that are completely incompatible with Objective C. When a CFArray is created, callback functions are provided. If the standard kCFTypeArrayCallBacks is provided, the array is indeed compatible and toll-free bridged to Objective C. However, it is possible to provide custom callback functions, and, for example, include value types as the array values (whereas NSArray requires that all values are CFType/objc_object).
It is important to know this difference, as in some rare cases, the Apple frameworks return CFArray objects which must not be bridged to NSArray, especially when using ARC.

NSNumber vs. primitive int for NSArray

I am learning Objective-C/Cocoa using the 4th edition of Cocoa Programming for Mac OSX. I apologize for the basic question but I'm one of those people that really need to understand the insides of everything in order for it to make sense to me and this book doesn't always do that to my needs. I've already picked up the basics of C++ and now I'm learning Obj-C so that is my background. This is a snippet of code that I'm learning...
for (i= 0; i < 10; i++) {
NSNumber *newNumber = [[NSNumber alloc] initWithInt:(i * 3)];
[array addObject:newNumber];
}
My question is why would you create instances of NSNumber to add to the array instead of just a single integer variable. It seems like it is just extra overhead creating a new instance each loop that could be avoided. But I'm sure the authors know what they are doing and there is a reason for it, could someone please explain?
NSArray can only hold objects, not primitive types. NSNumber and NSValue are used to wrap primitive types in objects, so they can be stored in foundation collections like NSArray, NSDictionary, and NSSet (and their mutable / ordered counterparts). As Peter Hosey points out in the comments:
The common term for this is "boxing" (as in boxing them up), and the inverse — extracting the primitive value from a box object — is unboxing.
Because Core Foundation classes are not able to work directly with primitive types, they can deal only with NSObject instances (which are objects in OOP terms, not primitives)
That's why you are forced to wrap your int variable with a NSNumber (or NSData or NSValue). This certainly brings some overhead, indeed if you need performance critical code, I suggest you to use Objective-C++ and rely on STL (eg std::vector<int>).
I personally had to discard all core foundation classes in favour of STL for big parts of a game engine just because they couldn't keep it up when managing large amounts of primitive data.
NSArray deals directly with pointers – and by extension, objects – whereas int is a primitive type. NSNumber exists to bridge this gap. An NSNumber can be cast from an int, float, or even a bool. The salient point is that it provides an object with a pointer, and that pointer can be added to the array.

Performance of mutable versus immutable objects

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.

Worth converting NSMutable<T> to NS<T>

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.

comparing NSCFString and NSCFBoolean

I am using SBJsonParser to parse JSON. An input can be 0 or a string (ex. a829d901093), and if it's zero, NSCFBoolean is returned, if its string NSCFString is returned. How can I tell which one is returned?
Thanks!
Calling these by their internal toll-free names is what makes this confusing. If you call them NSNumber and NSString (as they are listed in the documentation), then the answer is clear:
if ([value isKindOfClass:[NSNumber class]]) { ... }
EDIT: #Magnus points out that it isn't obvious that a NSCFBoolean isa NSNumber in order to look them up. That's true. To me it's very obvious because I know the Core Foundation type system and I know what the toll free bridge classes mean and how they're implemented (it's one of the coolest tricks in all of Cocoa IMO). But what if you didn't know those things? It's still no problem.
In the debugger, look in the variable list and expand the variable you care about. Its first "member" will be it superclass. Expand. Continue until you find a class you know.
Alternately, you can walk the superclasses using NSStringFromClass([object superclass]). Keep tacking superclass on for as many levels as you'd like to check.