Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have a textView which is displaying a string. I also have an array which keeps track of where every line begins, it stores the "start index" or NSRange.location for every line.

However, when text is inserted on one line, the start indexes of every line afterwards change. So I'm doing this:

 //i = the linenumber of the modified row 
 // self.lineStartIndexes = NSMutableArray
 for (int j = i+1; j < self.lineStartIndexes.count; j++) {
     _lineStartIndexes[j] = @([(NSNumber *)[self.lineStartIndexes objectAtIndex:j] intValue]+text.length);
 }

This takes 12ms on a large text file, and it feels like it could go a lot faster without all NSNumber-conversions. I have thought about using C arrays, but I don't know the size of the array and everything became very complicated to me. What should I do to optimize this?

share|improve this question

2 Answers 2

  1. You don't need (NSNumber *). -[NSArray objectAtIndex:] return id type and you can call any method on it.

  2. You can save and reuse the result of text.length so you don't need to call a method every time in the loop. Similarly for self.lineStartIndexes.count.

  3. [self.lineStartIndexes objectAtIndex:j] can be replaced with self.lineStartIndexes[j]

  4. Try use self.propertyName to access property. For performance reason you may want to use _propertyName directly but be consistent.

As result:

NSUInteger length = text.length;
NSUInteger count = self.lineStartIndexes.count;

for (int j = i+1; j < count; ++j) {
     self.lineStartIndexes[j] = @([self.lineStartIndexes[j] intValue]+length);
}

For performance improvement, using NSArray with NSNumber is very expansive. You should consider use C array (NSUInteger[]/NSUInteger *) if possible although you have to management the dynamic memory yourself with malloc and free.

For example:

@property NSUInteger * lineStartIndexes;

- (void)createLineStartIndexesWithSize:(NSUInteger)size
{
    free(lineStartIndexes);
    lineStartIndexes = calloc(size, sizeof(NSUInteger));
}

- (void)dealloc
{
    // other dealloc code
    free(lineStartIndexes);
}

then you can do

NSUInteger length = text.length;
NSUInteger count = self.lineStartIndexes.count;

for (int j = i+1; j < count; ++j) {
     self.lineStartIndexes[j] += length;
}
share|improve this answer

You could consider creating a class that holds the indices for a larger amount of text (for example a paragraph or a section or a subsection in the text). That class would have the absolute index for where in the file it begins and relative indices within the paragraph/section each line begins.

Whenever a new line is added or removed only the lines within that paragraph/section would have to be updated and the absolute start index of all the following sections as well.

(I don't know what text you write or what you use the line starts for).

You could still find a specific line very easily (and probably very fast) by enumerating the absolute indices of the paragraphs/sections and when you find the right section enumerate it's lines.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.