Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a simple 'live' word count in a UITextView

I'm trying to implement a simple char count of an UITextView while the user is typing in text (i.e. it should update continuously).

I have two problems.

(1) The first is that I don't know in which method I should put my charCount method. textViewShouldBeginEditing doesn't work, as it simply asks if an editing session should begin. textView:shouldChangeTextInRange doesn't work either, as it again asks if it is permitted to begin editing. I couldn't find other useful methods in the Apple doc.

(2) Next problem: I tried to call my charCount method from within another method. But I get the compiler error: 'ViewController' may not respond to 'charCount'.

Here is my humble attempt:

- (IBAction)charCount:(id)sender {

// all chars
int charsAsInt = (int)(textView.text.length);
NSString *newText = [[NSString alloc] initWithFormat:@"All chars: %d", charsAsInt];
allCharacters.text = newText;
[newText release];}

- (BOOL)textViewShouldBeginEditing:(UITextView *)aTextView {

    [self charCount];}

I guess it has to do with me trying to call a IBAction defined method that this won't work. But what would be the proper way to call a IBAction method from within a non-IBAction method?

As always, I'm sorry for these very basic questions and I do appreciate every little help to get my beginner's mind around this.

like image 367
n.evermind Avatar asked Mar 10 '11 10:03

n.evermind


4 Answers

I used to create like this, for prevent UITextview to type only 140 characters.
And i shown that count in UILabel like this

-(void)textViewDidChange:(UITextView *)textView 
{
   int len = textView.text.length;
   lbl_count.text=[NSString stringWithFormat:@"%i",140-len];
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if([text length] == 0)
    {
        if([textView.text length] != 0)
        {
            return YES;
        }
    }
    else if([[textView text] length] > 139)
    {
        return NO;
    }
    return YES;
} 

this may help for you!!!

like image 163
Suresh D Avatar answered Nov 18 '22 12:11

Suresh D


textView:shouldChangeTextInRange doesn't work either, as it again asks if it is permitted to begin editing.

but nothing will prevent you from counting the characters in there too. Just return YES at the end.

I guess it has to do with me trying to call a IBAction defined method that this won't work

You can call IBActions from code. IBAction is just a key word for Interface Builder, but it is the same as void.

But you have to use the correct method signature.
Your method - (IBAction)charCount:(id)sender has one parameter (id sender)
But your call [self charCount] has no parameter.

change it to [self charCount:nil] and you should be fine.


Edit: I don't have a textView right now and I'm too lazy to create one now but this works with a UITextField:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSInteger textLength = 0;
    textLength = [textField.text length] + [string length] - range.length;
    NSLog(@"Length: %d", textLength);
    return YES;
}

I add the length of the replacement string to the current text of the field. Then I subtract the length of the replacement range.
You should do some experimentation to better understand the relationship between those 3.
Basically if you overwrite some text the length of the range will be the length of the text you want to overwrite (ie the length of the text that is selected)

like image 34
Matthias Bauch Avatar answered Nov 18 '22 12:11

Matthias Bauch


Thanks to n.evermind and Mathias Bauch for their contributions. Below is my solution for UITextField, which combines information from both and works like a charm to set a character limit as well as render a label which keeps track of current characters for the user.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    int maxLength = 40;
    int textLength = [textField.text length] + [string length] - range.length;

    if(textLength > maxLength)
    {
        return NO;
    }
    else
    {
        //self.currentLabel in this case is just a UILabel
        //it formats the counter like: 0/40
        self.currentLabel.text = [NSString stringWithFormat:@"%i/%i",textLength,maxLength];
        return YES;
    }
}

Hope this helps!

like image 2
nightrise Avatar answered Nov 18 '22 14:11

nightrise


All you need to use is a textViewDidChange delegate implementation in your code. Here's a sample implementation you may need:

    #pragma-mark TextView Delegates

- (void)textViewDidChange:(UITextView *)textView
{
    NSLog(@"len:%d",textView.text.length);
    txtLength=textView.text.length;
    lblString=[NSString stringWithFormat:@"%i",210-txtLength];
    if(txtLength>200)
    {
        charactersLabel.textColor=[UIColor redColor];
    }
    charactersLabel.text=lblString;
}

Declare the three used variables in you header as:

int txtLength;
NSString *lblString;
IBOutlet UILabel *charactersLabel;

The label prints the characters left as you keep typing in and it's color changes to red when you go beyond 200 here. Finally don't forget to hookup the TextView's delegate to File's Owner & add the implementation for UITextViewDelegate in the header file. Hope it helps..

like image 2
Ankit Malhotra Avatar answered Nov 18 '22 13:11

Ankit Malhotra