Rot47 an NSString Category As a Java native, I am always a little worried when doing Objective-C because of memory leaks and pointers flying at my head...

All comments are welcome on the Category below.  The Category functions are correct.

GitHub

#import "NSString+r47.h"

@implementation NSString (r47)
-(NSString *) r47String
{
    const char *_string = [self cStringUsingEncoding:NSASCIIStringEncoding];
    int stringLength = [self length];
    char newString[stringLength+1];
    int x;
    for( x=0; x&lt;stringLength; x++ )
    {
        unsigned int aCharacter = _string[x];
        if( 0x20 &lt; aCharacter &amp;&amp; aCharacter &lt; 0x7F ) // from ! to ~
            newString[x] = (((aCharacter - 0x21) + 0x2F) % 0x5E) + 0x21;
        else  // Not an r47 character
            newString[x] = aCharacter;
    }
    newString[x] = '\0';
    NSString *rotString = [NSString stringWithCString:newString encoding:NSASCIIStringEncoding];
    DLog(@"%@ = %@",self,rotString);
    return rotString ;
}

@end
The question title suggested that this would be a Rot47 category on NSString, but it's not.  It's an r47 category (which tells me nothing... what's "r47"?).

This is Objective-C, not C or C++ or any other language where cryptic terseness is favored.  We prefer verboseness.  The category should be called Rot47.  This should be @implementation NSString (Rot47).  The method should be called - (NSString *)rot47String;



In Objective-C, we also prefer our opening braces go on the same line, not on their own line.  For example:

for (;;) {




Braces are technically optional, but you really shouldn't think of them as such.  Apple even agrees and made them non-optional in swift.  You've left them out of your if/else blocks, which is a great way to leave your code open for future bugs.



When we implement categories on Foundation classes, we should take care to ensure their portability.  The method should be designed to work no matter what project we import this file into and no matter what the contents of the string.

The problem here is that your method doesn't do that.  Your method works fine presuming a particular encoding, but for anything else it will produce incorrect results.

Rather than a char array, we need a unichar array.

NSUInteger length = [self length];
unichar letters[length + 1];

[self getCharacters:letters range:NSMakeRange(0,length)];


Now letters is an array of unichars for us to iterate over and transform correctly.