【问题标题】:How to implement a simple 'live' word count in a UITextView如何在 UITextView 中实现简单的“实时”字数统计
【发布时间】:2011-03-10 10:33:42
【问题描述】:

我正在尝试在用户输入文本时实现 UITextView 的简单字符计数(即它应该不断更新)。

我有两个问题。

(1) 首先是我不知道应该把我的charCount 方法放在哪个方法中。 textViewShouldBeginEditing 不起作用,因为它只是询问是否应该开始编辑会话。 textView:shouldChangeTextInRange 也不起作用,因为它再次询问是否允许开始编辑。我在 Apple 文档中找不到其他有用的方法。

(2) 下一个问题:我试图从另一个方法中调用我的 charCount 方法。但我得到编译器错误:“ViewController”可能不响应“charCount”。

这是我卑微的尝试:

- (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];}

我想这与我试图调用 IBAction 定义的方法有关,但它不起作用。但是从非 IBAction 方法中调用 IBAction 方法的正确方法是什么?

与往常一样,对于这些非常基本的问题,我深表歉意,我非常感谢能帮助我的初学者解决这个问题的每一个小帮助。

【问题讨论】:

    标签: iphone objective-c cocoa-touch uitextview


    【解决方案1】:

    我以前是这样创建的,为了防止 UITextview 只输入 140 个字符。
    我在 UILabel 中显示了这样的计数

    -(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;
    } 
    

    这可能对你有帮助!!!

    【讨论】:

    • 您是否禁用了视图中的粘贴功能?如果不是,那么很容易获得超过 140 个字符。选择 1 个字符并粘贴任意数量的文本。
    • @Suresh.D 有一个问题,正如 Matthias Bauch 所说,如果我复制文本并将其保留在 textView 上,它将超出我们从代码中限制的字符数与您的解决方案,我该如何解决。因为我希望剪切/复制/粘贴功能正常工作,同时限制用户输入的字符。
    • @iShwar 防止用户粘贴超过允许的内容,使用 UITextFieldTextDidChangeNotification 并在目标选择器中实现修剪,如下所示: if (myTextField.text.length > CHARACTER_MAX) { myTextField.text = [myTextField.text substringToIndex:CHARACTER_MAX]; }
    • 使它成为 NSInteger 而不是 int。否则,您将收到隐式转换问题的黄色小警告;)
    • @Suresh.D 谢谢
    【解决方案2】:

    textView:shouldChangeTextInRange 也不起作用,因为它再次询问是否允许开始编辑。

    但也没有什么能阻止您计算其中的字符。只需在最后返回 YES。

    我想这与我试图调用 IBAction 定义的方法有关,但这是行不通的

    您可以从代码中调用 IBActions。 IBAction 只是 Interface Builder 的一个关键词,但它和 void 是一样的。

    但是你必须使用正确的方法签名。
    您的方法- (IBAction)charCount:(id)sender 有一个参数(id sender)
    但是你的电话[self charCount]没有参数。

    把它改成[self charCount:nil]就可以了。


    编辑:我现在没有 textView,我懒得现在创建一个,但这适用于 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;
    }
    

    我将替换字符串的长度添加到字段的当前文本中。然后我减去替换范围的长度。
    您应该做一些实验来更好地理解这 3 个之间的关系。
    基本上,如果您覆盖某些文本,则范围的长度将是您要覆盖的文本的长度(即所选文本的长度)

    【讨论】:

    • 非常感谢!在过去的几天里,您真的很有帮助,陪伴我踏上了获得一点编程实践经验的旅程。我读过几本书,但没有什么比面对真正的问题并有如此友好的人提供帮助更愉快的了。再次感谢!
    • 我唯一的问题是更新总是落后1。例如。如果你输入 K,char count 会显示 0,如果你输入 KK,car count 会显示 1。我猜这是因为我调用了 shouldChange 方法……它只会在我输入 a 后更新计数信。有没有类似finishedTyping的方法?
    • 如果 UITextViews 使用“值更改”操作,您可以将您的计数方法连接到此操作。就像suresh建议的那样。但可以在shouldChangeCharacters... 中计算。请参阅我的编辑。您不能在额外的方法中执行此操作,因为您需要所有 3 个参数。
    【解决方案3】:

    您只需要在代码中使用textViewDidChange 委托实现即可。 这是您可能需要的示例实现:

        #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;
    }
    

    将标题中使用的三个变量声明为:

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

    标签会在您继续输入时打印剩余的字符,当您在​​此处超过 200 个时,它的颜色会变为红色。 最后不要忘记将 TextView 的委托连接到文件的所有者并在头文件中添加 UITextViewDelegate 的实现。 希望对你有帮助。。

    【讨论】:

    • 如果有一个 Swift3 的例子就好了
    【解决方案4】:

    感谢 n.evermind 和 Mathias Bauch 的贡献。下面是我针对 UITextField 的解决方案,它结合了两者的信息,并像一个魅力一样设置字符限制,并呈现一个跟踪用户当前字符的标签。

    - (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;
        }
    }
    

    希望这会有所帮助!

    【讨论】:

      【解决方案5】:

      使用颜色更新 UI 的实时字数统计代码片段。

      #define kCharacterMaximumLimit 120
      #define kCharacterWarningLimit 110
      
      - (void)textViewDidChange:(UITextView *)textView {
          NSString *substring = [NSString stringWithString:textView.text];
          _lblCount.text = [NSString stringWithFormat:@"%i", kCharacterMaximumLimit-[substring length]];
      
          if (substring.length == 0)
              _lblCount.text = @"";
      
          if (substring.length < kCharacterWarningLimit)
              _lblCount.textColor = [UIColor darkGrayColor];
      
          if (substring.length >= kCharacterWarningLimit && substring.length < kCharacterMaximumLimit)
              _lblCount.textColor = [UIColor redColor];
      }
      
      - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
      {
          if([text length] == 0)
          {
              if([textView.text length] != 0)
                  return YES;
              else
                  return NO;
          }
      
          if([[textView text] length] > kCharacterMaximumLimit-1)
              return NO;
      
          return YES;
      }
      

      【讨论】:

        【解决方案6】:

        @fluchtpunkt:效果很好!这是更新后的代码,以防万一有其他初学者在寻找答案:

        - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
        
        [self charCount:nil];
        
        // let the textView know that it should handle the inserted text
        return YES; }
        

        【讨论】:

        • 您好,您是如何解决一个字符但字符数为零、两个字符字符数为一等问题的?我遇到了同样的问题,找不到解决办法
        【解决方案7】:

        您可以使用此代码,假设您的视图中只需要 10 个字符,并且还想更新剩余计数

        假设 coutLabel 是我们必须更新的标签。 确保您将委托附加到 nib 文件或实现文件中。

        -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
        {
            NSInteger textLength = 0;
            textLength = [textView.text length] + [text length] - range.length;
            if(10-textLength==-1)
            {
                return NO;
            }
            coutLabel.text = [NSString stringWithFormat:@"%d characters remaining", 10-textLength];
        
            return YES;}
        

        【讨论】:

          【解决方案8】:

          我们在这里寻找最佳拟合。

          var charCount = 0;
          let maxLength = 150
          func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
          
              if text == "" // Checking backspace
              {
                  if textView.text.characters.count == 0
                  {
                      charCount = 0
                      characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
                      return false
                  }
                  charCount = (textView.text.characters.count - 1)
                  characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
                return true
              }
              else
              {
                  charCount = (textView.text.characters.count + 1)
                  characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
          
                  if charCount >= maxLength + 1
                  {
                      charCount = maxLength
                      characterCount.text = String(format: "%i Characters Left", maxLength - charCount)
                      return false;
                  }
              }
              return true
          }
          

          【讨论】:

            【解决方案9】:

            对于新手来说,一个更简单的方法是实现一个每秒检查一次长度的 NStimer

            为此添加“NSTimer countTimer;”添加到您的 .h 中,然后将其添加到您的 .m

            -(void)viewDidLoad {

            countTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(countTextView) userInfo:nil repeats:YES];
            

            }

            -(void)countTextView{

            [countTimer invalidate];
            int currentChars = [TextView.text length];
            
            if ([TextView.text length]>100) {
                UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Too long"
                    message:[NSString stringWithFormat:@"Only 100 chars allowed."]
                    delegate:nil
                    cancelButtonTitle:@"OK"
                    otherButtonTitles:nil];
                [alert show];
                [alert release];
                TextView.text = [TextView.text substringToIndex:100];
            }
            
            counterLabel.text = [NSString stringWithFormat:@"%d",currentChars];
            
            countTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(countTextView) userInfo:nil repeats:YES];
            

            }

            【讨论】:

            • “更简单”的方式也是更糟糕的方式,不要这样做。让textview告诉你它什么时候改变了,不要一直重复检查。
            猜你喜欢
            • 2021-09-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多