UITextview 设置属性文本导致性能下降

UITextview set Attribute Text cause Performance slow

我是 iOS 的初学者。我想在用户输入时设置 UITextview 属性文本,没关系,但问题是性能滞后,而且速度太慢。我不知道发生了什么事。我将不胜感激您的任何帮助!谢谢

  
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
       
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineBreakMode = .byWordWrapping
        paragraphStyle.alignment = .left

        let alignTextAttributes = [
            NSAttributedString.Key.kern : 30,
            NSAttributedString.Key.paragraphStyle : paragraphStyle,
            NSAttributedString.Key.foregroundColor : UIColor.black,
         
            ]
        as [NSAttributedString.Key : Any]
       
        let atribute = NSAttributedString(string: text, attributes: alignTextAttributes)
        
        

       
        var cursorLocation = textView.selectedRange.location
        if text == ""{
            textView.textStorage.replaceCharacters(in: range, with: atribute)
           cursorLocation -= 1
          
           
        }else{

            textView.textStorage.replaceCharacters(in: range, with: atribute)
            cursorLocation += 1
        }
     
       textView.selectedRange.location = cursorLocation

       //add attachment image to another uitextview
        let attachment = NSTextAttachment()
        let imageNew = UIImage(named: "icon")
        attachment.image = imageNew

       let attString = NSAttributedString(attachment: attachment)
       txtViewAnother.textStorage.replaceCharacters(in: range, with: attString)
 
        return false
                
      }

尝试删除光标位置更改的最后一行,看看这是否是性能下降的原因。如果是这样,请稍等片刻后尝试执行此部分:

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .milliseconds(5)) {[weak self] in
        self?.myTextView.selectedRange.location += 1
    }

你所做的可以概括为-

  1. 添加段落样式和其他文本属性。
  2. 读取 attributedText 的旧值,使用所有这些数据重新创建 NSAttributedString 的新实例。
  3. 手动管理光标位置(向后删除 (-1) vs 添加字符 (+1))
  4. 手动更新textView.textStorage
  5. return false - 不允许系统控制输入。

此处还有许多其他详细信息,UITextView 会自动为您涵盖 - 如果您允许系统控制输入。例如-

You are not accounting for what happens when user selects a range of characters and hits backward delete. (-1 won't cover for this case).

下面的代码与您当前的代码完全相同 -

// Initialize once and reuse every time
lazy var paragraphStyle: NSMutableParagraphStyle = {
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineBreakMode = .byWordWrapping
    paragraphStyle.alignment = .left
    return paragraphStyle
}()

// Initialize once and reuse every time    
lazy var alignTextAttributes: [NSAttributedString.Key: Any] = {
    return [
        .kern : 30,
        .paragraphStyle : paragraphStyle,
        .foregroundColor : UIColor.black,
    ]
}()
    
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    // If I want to set each characters with different kern values, how can I do that?
    alignTextAttributes[.kern] = textView.text.count.isMultiple(of: 2) ? 30 : 10

    // This is the key part
    textView.typingAttributes = alignTextAttributes

    // Allow system to control typing
    return true
}