【问题标题】:Limit number of characters in uitextview限制uitextview中的字符数
【发布时间】:2011-01-30 08:07:48
【问题描述】:

我正在提供一个文本视图来推文一些字符串。

我正在应用以下方法将字符数限制为 140 个长度。

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
   return [[textView text] length] <= 140;
}

除了退格不起作用的第一个条件之外,代码运行良好。 假设我已经达到了 140 个字符的限制,因此该方法会给我 false 并且用户不能插入更多字符,但是之后当我尝试删除一些字符时,文本视图的行为就像它被禁用一样。

所以问题是:“如何从textview.text 中删除字符或重新启用文本视图?”

【问题讨论】:

标签: ios iphone uitextview uitextviewdelegate


【解决方案1】:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    return textView.text.length + (text.length - range.length) <= 140;
}

这说明用户剪切文本,或删除长于单个字符的字符串(即,如果他们选择然后按退格键),或突出显示范围并粘贴比它更短或更长的字符串。

Swift 4.0 版本

 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    return textView.text.count + (text.count - range.length) <= 140
}

【讨论】:

  • 这是一个 IBAction 吗?作为用户类型,我如何将它连接到有问题的 TextView?
  • 必须让您的视图控制器成为 UITextViewDelegate,然后将文件的所有者作为文本视图的委托人
  • 我认为问一个后续问题会更公平:我遇到了两个 UITextviews 需要在同一个控制器中进行字符限制的问题。你会帮忙吗? stackoverflow.com/questions/25272413/…
  • 这应该被标记为正确的响应。谢谢
  • 如果您粘贴的文本太长而无法容纳(因此将返回false),这将导致崩溃,然后您将尝试撤消该操作。
【解决方案2】:

正如apple reference 所说,您应该寻找一个空字符串

如果用户按下 Delete 键,则范围的长度为 1,并且一个空字符串对象替换该单个字符。

我认为您实际上想要进行的检查类似于[[textView text] length] - range.length + text.length &gt; 140,以说明剪切/粘贴操作。

【讨论】:

  • 谢谢,但可以更具体我看不懂苹果的技术规范
  • 告诉我我应该在第一个条件中放什么。我为此花了将近 4 个小时
  • 我认为您实际想要进行的检查类似于[[textView text] length] - range.length + text.length &gt; 140,以说明剪切/粘贴操作。
  • [[textView text] length] - range.length + text.length > 140 应该是 [[textView text] length] - range.length + text.length
  • Kuzon,如果您默认返回 true,如果超过 140 个字符限制,则希望返回 false。
【解决方案3】:

对于 Swift 4:

//MARK:- TextView Delegate
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    //300 chars restriction
    return textView.text.count + (text.count - range.length) <= 300
}

【讨论】:

    【解决方案4】:

    但是你也可以使用下面的工作代码..

    - (void)textViewDidChange:(UITextView *)textView{
    
        NSInteger restrictedLength=140;
    
        NSString *temp=textView.text;
    
        if([[textView text] length] > restrictedLength){
            textView.text=[temp substringToIndex:[temp length]-1];
        }
    }
    

    【讨论】:

    • 通常不是设置后编辑的首选方式。最好在“shouldChangeCharactersInRange”中检查这一点,以防止文本被编辑。
    【解决方案5】:

    ? 限制溢出,而不是整个文本!

    通过在...shouldChangeTextInRange... 委托方法中返回false,您实际上是在限制整个文本并且处理以下情况可能非常困难:

    • 复制和粘贴
    • 选择文本区域并进行编辑
    • 使用自动建议
    • 使用语音输入(语音命令或听写)

    所以你可以:

    ?只需限制文本溢出!

    通过删除多余的字符:

    textView.text = String(textView.text.prefix(140))
    

    您甚至可以即时进行!通过将此代码放在textViewtextFieldaction 中,并带有.editingChanged 事件。

    【讨论】:

    • 将它放在 UITextView 委托的 func textViewDidChange(_ textView: UITextView) {...} 中效果很好,只会裁剪长粘贴文本的结尾
    【解决方案6】:

    在 Swift 5 和 iOS 12 中,尝试以下实现 textView(_:shouldChangeTextIn:replacementText:) 方法,该方法是 UITextViewDelegate 协议的一部分:

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        guard let rangeOfTextToReplace = Range(range, in: textView.text) else {
            return false
        }
        let substringToReplace = textView.text[rangeOfTextToReplace]
        let count = textView.text.count - substringToReplace.count + text.count
        return count <= 10
    }
    
    • 这段代码最重要的部分是从range (NSRange) 到rangeOfTextToReplace (Range&lt;String.Index&gt;) 的转换。请参阅此video tutorial,了解为什么这种转换很重要。
    • 要使此代码正常工作,您还应该将textFieldsmartInsertDeleteType 值设置为UITextSmartInsertDeleteType.no。这将防止在执行粘贴操作时插入(不需要的)额外空间。

    下面的完整示例代码展示了如何在UIViewController 中实现textView(_:shouldChangeTextIn:replacementText:)

    import UIKit
    
    class ViewController: UIViewController, UITextViewDelegate {
    
        @IBOutlet var textView: UITextView! // Link this to a UITextView in Storyboard
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            textView.smartInsertDeleteType = UITextSmartInsertDeleteType.no
            textView.delegate = self
        }
    
        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            guard let rangeOfTextToReplace = Range(range, in: textView.text) else {
                return false
            }
            let substringToReplace = textView.text[rangeOfTextToReplace]
            let count = textView.text.count - substringToReplace.count + text.count
            return count <= 10
        }
    
    }
    

    【讨论】:

      【解决方案7】:

      斯威夫特:

      // MARK: UITextViewDelegate
      
      let COMMENTS_LIMIT = 255
      
      func textView(textView: UITextView,  shouldChangeTextInRange range:NSRange, replacementText text:String ) -> Bool {
          return count(comments.text) + (count(text) - range.length) <= COMMENTS_LIMIT;
      }
      

      【讨论】:

      【解决方案8】:

      这个

      - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
      {
      
          int limit = 139;
      
          return !([textField.text length]>limit && [string length] > range.length);
      
      }
      

      这只会输入140个字符,如果需要你可以删除它们

      【讨论】:

        【解决方案9】:

        虽然我需要一个if-else 条件,所以这对我有用:

        - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
        {
            BOOL status = textView.text.length + (text.length - range.length) <= 15;
            if (status)
            {
                [self.btnShare setEnabled:YES];
                [self.btnShare setAlpha:1];
            }
            else
            {
                [self.btnShare setEnabled:NO];
                [self.btnShare setAlpha:0.25];
            }
            return status;
        }
        

        按钮最初设置为禁用。但是,如果您希望用户不能发布空测试,只需在按钮单击上设置一个条件:

        - (void)btnShare_click:(id)sender
        {
            NSString *txt = [self.txtShare.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
            if ([txt length] == 0)
            {
                [self.btnShare setEnabled:NO];
                [self.btnShare setAlpha:0.25f];
                [[[UIAlertView alloc]initWithTitle:nil message:@"Please enter some text to share." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
                return;
            }
            .
            .
            .
            .
            .
            .
            // rest of your code
        }
        

        【讨论】:

          【解决方案10】:

          上面给出的一些答案的问题是,例如我有一个文本字段,我必须设置输入 15 个字符的限制,然后在输入第 15 个字符后停止。但他们不允许删除。那就是删除按钮也不起作用。因为我面临同样的问题。提出了解决方案,如下所示。非常适合我

          - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
          {
           if(textField.tag==6)
           {
              if ([textField.text length]<=30)
              {
                  return YES;   
              }
              else if([@"" isEqualToString:string])
              {
                  textField.text=[textField.text substringToIndex:30 ];
              }
          
              return NO;
           }
           else
           {
              return YES;
           }
          }
          

          我有一个文本字段,我已将其标签设置为“6” 我已经限制了最大字符限制 = 30 ; 在任何情况下都可以正常工作

          【讨论】:

            【解决方案11】:

            @Tim Gostony 的 Swift 版本:

            // restrict the input for textview to 500
            func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
                return count(textView.text) + (count(text) - range.length) <= 500;
            }
            

            【讨论】:

              【解决方案12】:

              我们在这里寻找最合适的。 显示剩余字符数:'n' 个字符。

              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
              }
              

              【讨论】:

                【解决方案13】:

                如果您还希望能够将代码粘贴到最大字符数,同时切断溢出并更新计数标签:

                let maxChar: Int
                let countLabel: UILabel
                
                func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
                    let oldChar = textView.text.count - range.length
                    let oldRemainingChar = maxChar - oldChar
                    let newChar = oldChar + text.count
                    let newRemainingChar = maxChar - newChar
                    let replaceChar = newRemainingChar > 0 ? text.count : oldRemainingChar
                
                    if
                        let textRange = textView.textRange(for: range),
                        replaceChar > 0 || range.length > 0
                    {
                        textView.replace(textRange, withText: String(text.prefix(replaceChar)))
                        countLabel.text = String(describing: maxChar - textView.text.count)
                    }
                
                    return false
                }
                

                带有扩展名:

                extension UITextInput {
                    func textRange(for range: NSRange) -> UITextRange? {
                        var result: UITextRange?
                
                        if
                            let start = position(from: beginningOfDocument, offset: range.location),
                            let end = position(from: start, offset: range.length)
                        {
                            result = textRange(from: start, to: end)
                
                        }
                
                        return result
                    }
                }
                

                【讨论】:

                  【解决方案14】:

                  试试这个:-

                   func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
                      print("chars \(textView.text.count) \( text)")
                  
                      if(textView.text.count > 20 && range.length == 0) {
                          print("Please summarize in 20 characters or less")
                          return false
                      }
                      return true
                  }
                  

                  【讨论】:

                    【解决方案15】:

                    textView:shouldChangeTextInRange:replacementText:方法中编写以下代码:

                    if ([textView.text length]>=3 && ![text isEqualToString:@""]) {
                        return NO;
                    }
                    return YES;
                    

                    【讨论】:

                      【解决方案16】:

                      Swift5:

                      let maxChars = 255
                      
                      func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
                        if maxChars - aTextView.text.count == 0 {
                          if range.length != 1 {
                          return false
                          }
                        }
                        return true
                      }
                      

                      【讨论】:

                        【解决方案17】:

                        使用以下代码。

                        - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
                        {
                            if(text.length == 0)
                            {
                                return YES;
                            }
                            else if(self.txtViewComments.text.length > 255)
                            {
                                return NO;
                            }
                            else
                            {
                                return YES;
                            }
                        }
                        

                        【讨论】:

                        • if 条件用于从文本视图中删除字符
                        【解决方案18】:

                        这是限制用户在 iOS swift 中在 UITextFieldUITextView 中输入字符数的最简单解决方案

                        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 
                        {
                           return textField.text!.count < limit ? true : false
                        }
                        

                        注意:根据您的要求,此处的限制可以是从 1n 的任何值,例如:如果您使用的电话号码超过 limit,则值将是 10 如果您想在UITextView 上应用相同的方法,只需更改方法,在textfield 的位置您将使用textview

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2012-12-13
                          • 2015-10-20
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-12-12
                          相关资源
                          最近更新 更多