Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

RD92

macrumors newbie
Original poster
Jul 16, 2007
4
0
Hi, I created an app that counts the lines in a text view. I got it to work like this:

- (void)awakeFromNib
{
string = [textView string];
unsigned numberOfLines;
unsigned index;
unsigned stringLength = [string length];
for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
{
index = NSMaxRange([string lineRangeForRange:NSMakeRange(index, 0)]);
[textField setIntValue:numberOfLines + 1];
}
}

I put '+ 1' because, I don't know why, it starts from zero. It works perfectly except It just counts them once. If you modify the text view, the text field doesn't change. How can I make it to coninuously check for changes in the text view?
 
You don't want to continuously check for changes: this will use a large amount of CPU (this solution is called polling and, in general, is something we try and avoid).

The better solution would be to have the text view tell you when there is a change and re-count then.

To do this set your instance as the delegate of the view. You then have a number of methods you could implement.

The textDidChange: method of NSText would work, although from memory this would only get called when editing ends (i.e. you select another control) so is probably not what you want.

A better method might be to implement - (BOOL)textView:(NSTextView *)aTextView shouldChangeTextInRange:(NSRange)affectedCharRange replacementString:(NSString *)replacementString. Remember to return YES from this! This should get called on all changes to the text.
 
Also, a for loop isn't particularly suitable here. Try this:

Code:
unsigned numberOfLines = 0;
unsigned index = 0;
while (index < [[textView string] length])
{
	index = NSMaxRange([[textView string] lineRangeForRange:NSMakeRange(index, 0)]);
	++numberOfLines;
}
[textField setIntValue:numberOfLines];

(I know this wasn't part of your question, so sorry if this is unwelcome advice.)
 
@RD I think you are wrong, I think textDidChange does get called every time you type a character, at least certainly one of the delegates of NSText or NSTextField does. I think textDidEndEditing only gets called when you end editing ;).


I'd love to help find which method but I changed my code to use bindings instead.
 
@RD I think you are wrong, I think textDidChange does get called every time you type a character, at least certainly one of the delegates of NSText or NSTextField does. I think textDidEndEditing only gets called when you end editing ;).

In that case that would be great. I have distinct memories of it not being called on very character change in an NSTextField though. I could be thinking of another delegate method though.

The simplest thing would be to try it!

Another reason for suggesting the other method was that it tells you the range being effected and the new characters. So you could use this data to update the count without a full recount which could save a lot of CPU time on a very long document...
 
Another reason for suggesting the other method was that it tells you the range being effected and the new characters. So you could use this data to update the count without a full recount which could save a lot of CPU time on a very long document...

True, it did seem to be very inefficient to do it my way.
 
Ok, I switched to textDidChange:NSTextDidEndEditingNotification but I have no idea how to count only the characters that have been added. Here's my code:

Code:
- (void)textDidChange:NSTextDidEndEditingNotification
{
	linesString = [textView string];
	unsigned numberOfLines;
	unsigned index;
	unsigned stringLength = [linesString length];
	for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
	{
		index = NSMaxRange([linesString lineRangeForRange:NSMakeRange(index, 0)]);
		[linesField setIntValue:numberOfLines + 1];
	}
}
 
There's no need to update your text field every single time. Just do it once at the end. Also, isn't componentsSeparatedByString: a more simpler way to count the # of lines?

Edit: Use Nutter's code. Much easier to read and more efficient.
 
Ok, thanks it worked perfectly. Just one more thing, how can I get the current line that the insertion point is in?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.