Monday, July 26, 2010

The wonders of NSString

This post is much less of a rant, and more of a regurgitation of how to use NSString as a way to solidify it in my memory and provide a useful way to look it up (I think it'll get buried and I'll forget about this post, making it a form of future e-waste.  Where e-waste is knowledge that accumulates, but serves no purpose in the present except take up space.).

So... the lowly NSString.  Where shall I begin?  Maybe with the simple idea that whatever text processing I needed to do, NSString (and supporting objects) always seems to provide a means to do it (sometimes thanks to methods added after-the-fact to the NSString object).  And also that getting a C string is almost never needed unless interacting with a C library (the standard C library shouldn't be needed).

NSString is very similar (for historical reasons) to Java's String object.  Both can not be changed after being created, changes are rather require the creation of a new object (In such cases - NSAutoReleasePool is your friend if you find yourself doing innumerable string manipulations):
NSAutoreleasePool *p
    = [[NSAutoreleasePool alloc] init];
//Do plenty of string operations using
//[NSString string*] methods.
[p release];

That's the beginning. Ok; time for some fun! Let's say there are plenty of string constants that need to be internationalized? The simplest solution is to write the following for strings:
NSString *s = NSLocalizedString(@"Hello", @"Greeting String");
If you've set up your translation files correctly (get them using genstrings), then "Hello" is the word to get in the current language, and "Greeting String" is a hint to the translator.

Can we do more with NSString? Of course! splitting, loading a string from a file, and all sorts of other operations can be done.

I'll just note a few objects that can be useful rather than give a complete tutorial on them (the Apple docs are very good).

NSCharacterSet defines a set of unicode characters.  This object provides a quick way to get all white-space, all punctuation, and even all newline character sets.  Very useful when parsing files or breaking up strings.

NSScanner provides a nice way to scan any arbitrary file.  It is much more flexible than the standard C/C++ file operations in that it returns the data (String, float, etc. - even delimited to an NSCharacterSet) and a boolean specifying whether the data was obtained.  This makes parsing more complex files... easier.  (I don't doubt that it can be done in C/C++ - just that assuming the structure might vary rather than be fixed is a nice one.  eg.  optional floating-point number would be read as 0 in C++ if memory serves.)

NSXMLParser is nice - but I'm not really a fan of XML.  Let's say that there are neater ways to represent data than XML.  XML is nice for being standard - but the tags are just too much for me.  But it's there and works great!

NSString can also do everything that the standard C library does.  Just that I don't worry about memory buffer sizes.  I'm not familiar enough with the C++ String class to comment on it.

And for speed, CFString allows quick access to the underlying data:
//Direct cast -
//toll-free-bridge as Apple calls it.
CFStringRef r = (CFStringRef)@"NSString";
CFStringLineBuffer b; //... inline buffer used to iterate...
So yes - this has devolved into a rant. It's conclusion: look at what NSString does. It does a lot more than what you think. Especially thanks to categories that allow for any programmer to give NSString more functionality (that's how it can render text to views - and how external libraries could use it - to render strings to textures, etc.).

Unfortunately, this is true of most modern APIs - and for all objects. That is; the objects can do so much. It's no longer a question of knowing how to do something - but knowing the magic keyword that will return the proper function in a search result.

OK, a mini-rant,

<rant>
Programmers now work at such a high-level. And that high-level will allow us to keep on coding as normal while everything transparently becomes parallel (something I've been thinking a lot about recently - the challenge may appear great; but in retrospect abstraction makes it easier. As a hint - we parallelize like the CPU does with instructions. Branches are our undoing - yes I'm captain obvious. I think QT Concurrent is the closest to what I'm thinking - but there is a way to provide a sequential API with parallel underpinnings. It already in the form of OpenGL. The real trick - which I'm almost done tinkering with - is how to get modules that don't know about each other communicating in a relevant way in parallel.).
</rant>

No comments:

Post a Comment