Thotz/Thotz.html
 

lines

The following categories on NSString separate a text file into lines. “lines” is the one I use the most.  I often have simple text lists in my application resources, and use lines to painlessly import them into an NSArray. By avoiding plists, I make it possible to easily edit the list contents without specialized knowledge or a plist editor.

While it is tempting to just use:

     [aString componentsSeparatedByString: @”\n”]

   – it isn’t very robust. There are a lot of ways to delimit a line.

These methods use NSString’s getLineStart:end:contentsEnd:forRange:.

This method isn’t well documented, but it provides a very robust definition of a line ending. And if a new one comes along, Apple will probably update their method to handle it, and I won’t have to.


@implementation NSString (HKNSStringLinesFromString)


- (NSArray *) lineRanges

{

    NSArray * result = nil;

    NSAutoreleasePool * pool = [NSAutoreleasePool new];

    unsigned stringLength = 0;

    unsigned startIndex, lineEndIndex, contentsEndIndex;

    //    NSArray * array;

    NSMutableArray * lineRanges = [NSMutableArray array];

    NSAutoreleasePool * loopPool = nil;

    NSRange range = NSMakeRange(0,0);

    stringLength = [self length];

    lineEndIndex = 0;

    // while test uses C's logical evaluation rules to avoid leftover pool

    while((lineEndIndex < stringLength) && (loopPool = [NSAutoreleasePool new]))

        {

        NSRange lineRange = NSMakeRange(0,0);

            [self getLineStart:&startIndex end:&lineEndIndex 

            contentsEnd:&contentsEndIndex forRange:range];

        lineRange.location = startIndex;

        lineRange.length = (contentsEndIndex-startIndex);

        [lineRanges addObject:[NSValue valueWithRange:lineRange]];

        range.location = lineEndIndex;

        }

    result = [lineRanges copy];

    [pool release];

    return [result autorelease];

}


- (NSArray *) lines

{

    NSArray * result = nil;

    NSAutoreleasePool * pool = [NSAutoreleasePool new];

    unsigned stringLength = 0;

    unsigned startIndex, lineEndIndex, contentsEndIndex;

    //    NSArray * array;

    NSMutableArray * lines = [NSMutableArray array];

    NSRange range = NSMakeRange(0,0);

    NSAutoreleasePool * loopPool = nil;

    stringLength = [self length];

    lineEndIndex = 0;

    // while test uses C's logical evaluation rules to avoid leftover pool

    while((lineEndIndex < stringLength) && (loopPool = [NSAutoreleasePool new]))

        {

        NSString * line;

        NSRange lineRange = NSMakeRange(0,0);

        [self getLineStart:&startIndex end: &lineEndIndex

            contentsEnd:&contentsEndIndex forRange:range];

        lineRange.location = startIndex;

        lineRange.length = (contentsEndIndex-startIndex);

        line = [self substringWithRange:lineRange];

        if(line)

            {

            [lines addObject:line];

            }

        range.location = lineEndIndex;

        [loopPool release];

        }

    result = [lines copy];

    [pool release];

    return [result autorelease];

}

@end