How do I Sort Collections in Objective-C? - objective-c

I have an integer array in my Objective-C program. I'd like to sort it (ascending or descending, doesn't matter). In C++ I'd use the sort algorithm in the STL Algorithm library. How can I do this?

The "Cocoa" way is to create NSNumber objects, add them to an NSArray, and use the sortUsingSelector:#selector(compare:) method (or one of the other NSArray sort methods).
If you want to create a C array of primitive NSInteger (int) values, you can use the built-in qsort(…) function of C.

Even though this question has already been answered, I would like to add that you can also use STL collections with Objective-C++ and iPhone programming. Here is a link to a previous discussion on the topic.

Related

NSDictionary lookups with +valueWithPointer: keys are too slow

I have an Objective C++ class, instances of which are required to store an arbitrary set of C++ objects and associate each with a corresponding Objective C object. Looking up the Objective C objects when given the C++ object is killing my performance, so I'm looking for a better solution.
I'm currently storing the pairs in an NSMutableDictionary after creating the keys using [NSValue valueWithPointer:]. The lookup time, in which +valueWithPointer: is about twice as expensive as -objectForKey:, is simply too slow.
The C++ objects are in a third-party framework, and do not provide any unique identifier.
The sets of C++ objects are always smaller than a dozen elements.
What is a faster approach to performing these lookups?
I see three approaches that seem worth trying:
Use NSMapTable
Use objc_setAssociatedObject
Use std::unordered_map or std::map
objc_setAssociatedObject uses std::unordered_map behind the scenes.
I had a similar issue recently with [NSValue valueWithNonRetainedObject:] being too slow.
The solution I went with was to drop down a level and use CoreFoundation's CFMutableDictionary. I would suggest you take a look at it: CFMutableDictionary Reference. It takes regular C pointers in CFDictionaryAddValue(), CFDictionaryRemoveValue, so it's the best thing to use to interface Obj-C and C++ (C is their common denominator).
The reason I'd rather do that than use an std::unordered_map is because I tend to want to minimise C++ in these kind of things. Obj-C++ is a bit of a hack and it's best to just reduce it to glue code between real Obj-C and existing C++ code.

C style array in Objective-C

With all the useful things you get from NSArray and NSMutableArray, why would you ever use a "C Style" array with Objective-C objects?
NSString *array[] = {#"dog", #"cat", #"boy"};
For short, fixed arrays, the availability of a nice compact initialization syntax (as you've demonstrated) can be nice. In certain cases, a C style array may also offer a performance benefit compared to using NSArray. Another thing that comes to mind is that NSArray doesn't offer any built in support for multidimensional arrays, while multidimensional C arrays are easy.
And of course, there's the fact that you can only store objects in NSArray, not C-primitive types, but you asked specifically about using C arrays with Objective-C objects.
All useful things come at a price.
Ever try making an NSArray of ints? You can't. You MUST use NSNumber.
Why? Because NSArray doesn't know what to do with things it doesn't know how to memory-manage... and the only things that conform to it's memory-management requirements are things based on NSObject.
It's just one example, but there are plenty of others.
Bottom line is, there is rarely ever one single "best" answer to anything. NSArray is no exception.

More convenient NSArray and NSDictionary access

Note that this is merely an academic question.
In Ruby, you can access array and dictionary(hash) elements conveniently:
value = myHash['myKey']
In Objective C, you need a method call:
value = [myDict objectForKey:#"myKey"];
How might one override some type of brackets or define a macro to bring the Objective C syntax closer to Ruby's?
Just an update:
Starting with iOS 6 I guess, you CAN use such a syntax:
value = dictionary[#"key"];
This is equivalent to
value = [dictionary objectForKey:#"key"];
Moreover, if we're talking about NSMutableDictionary, you can add new objects into a dictionary like this:
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
dictionary[#"a"] = #"A";
NSLog(#"%#",dictionary[#"a"]);
What you are trying to do requires a language feature called "operator overloading". Objective-C does not allow for operator overloading because the designers of the language felt that operator overloading was harmful more often than it was helpful.
C++ does allow for operator overloading, so one way to get the syntax you want is to wrap your collections in C++ classes and use those instead. To switch to Objective-C++, just change your implementation files' extensions from .m to .mm.
Personally, I would recommend against using C++ wrappers around collections because it will make your code harder for other Objective-C programmers to read and it will break some of the more advanced features of Xcode. For example, you will no longer be able to use the refactor tools, because Xcode will not be able to parse your code correctly.
The other answers have told you why you can't do it - or how to work around it, but Objective-C is a verbose language - and using descriptive names is part of the pleasure of the language. Sure, you are typing a few more letters, but with code completion it's hardly any slower to write and you can see exactly what you are doing.
Switch to Objective-C++, define C++ wrapper classes for NSDictionary and NSMutableDictionary, and override operator, the array subscript operator.

What is the meaning of the "mutable" in objective C?

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.

cannot convert 'b2PolygonShape' to 'objc_object*' in argument passing

I am not sure if many of you are familiar with the box2d physics engine, but I am using it within cocos2d and objective c.
This more or less could be a general objective-c question though, I am performing this:
NSMutableArray *allShapes = [[NSMutableArray array] retain];
b2PolygonShape shape;
..
..
[allShapes addObject:shape];
and receiving this error on the addObject definition on build:
cannot convert 'b2PolygonShape' to 'objc_object*' in argument passing
So more or less I guess I want to know how to add a b2PolygonShape to a mutable array. b2PolygonShape appears to just be a class, not a struct or anything like that. The closest thing I could find on google to which I think could do this is described as 'encapsulating the b2PolygonShape as an NSObject and then add that to the array', but not sure the best way to do this, however I would have thought this object should add using addObject, as some of my other instantiated class objects add to arrays fine.
Is this all because b2PolygonShape does not inherit NSObject at it's root?
Thanks
b2PolygonShape is a C++ class, not an ObjC class. You can only put ObjC instances into "NS-containers".
Since you need C++ anyway, it's better to use a std::vector<b2PolygonShape>.
NS-container classes can (as KennyTM pointed out) only store NSObjects. This can be a bit of a pain sometimes. But there are plenty of alternatives to NS-containers.
You can write Objective-C wrapper classes (or use NSValue), and store these in an NSArray.
You could use a plain old C array (though, that may not serve your needs, if the array size is undefined and shrinks and grows)
You could use a hash table to store your references.
A linked list of structs can also come in handy, and is fairly easy to create and maintain.
Should you decide to stick to std::vector, which is as good a solution as any, you can read more about that at: http://www.cplusplus.com/reference/stl/vector/