2017-09-16 70 views
0

我想创建一个UITextView,在选择后,将用户句柄添加到文本的开头。永久追加文本到UITextView

我的理解是可能创造另一个UITextView的,并将它放置到第二UITextView的左侧,使其看起来就像它们是同一系列的一部分,但是,它们的目的将是如果两个部分都容易得多部分相同的文本...

这里是我正在使用的函数以及它正在使用的一个例子。

func addHandle(text:String, handle:String) -> NSAttributedString { 

    let convertedText = NSMutableAttributedString() 

    let h = NSMutableAttributedString(string: handle) 
    h.beginEditing() 

    let m = NSMutableAttributedString(string: text) 
    m.beginEditing() 


    do { 
     m.addAttributes([NSFontAttributeName: UIFont.init(name: "PingFangSC-Regular", size: 18)], range: (m.string as NSString).range(of: m.string)) 
     h.addAttributes([NSFontAttributeName: UIFont.init(name: "PingFangSC-Medium", size: 18)], range: (h.string as NSString).range(of: h.string)) 

     convertedText.append(h) 
     convertedText.append(m) 

     m.endEditing() 
     h.endEditing() 
    } 
    return convertedText 
} 

let myHandle = "Johnny: " 
let myMessage = "This is a test" 

addHandle(text: myMessage, handle: myHandle) 

在这种情况下,句柄和消息都可以连接在一起。

但是,当文本发生变化时,如下所示,由于句柄是新文本的一部分,因此它会再次运行该函数并再次添加句柄。

func textViewDidBeginEditing(_ textView: UITextView) { 
    let currentString: String = textView.text! 
    self.t.searchBar.attributedText = addHandle(text: currentString, handle: "Johnny: ") 
} 

func textViewDidChange(_ textView: UITextView) { 

    let currentString: String = textView.text! 
    self.t.searchBar.attributedText = addHandle(text: currentString, handle: "Johnny: ") 

    UIView.animate(withDuration: 0.15, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { 
     self.view.layoutIfNeeded() 
    }, completion: { (completed) in 

    }) 
} 

我应该如何去改变我的功能或执行,以确保

  1. 手柄永远是第一位的消息
  2. 用户不能从文本删除手柄前

以下应该是可能的:

Johhny:测试消息

约翰尼:

这应该是不可能的

Johnn

有什么建议?

编辑: 下面是显示当前行为的屏幕截图。 手柄是“约翰尼:”与键入的文本是‘这’

enter image description here

+0

一个良好的开端你的问题。我明白你想做什么,代码看起来不错(到目前为止)。但是 - 我怎样才能重现你面临的问题?我不知道它是什么。 (我得到什么不应该可能,但我该如何重现它?) – dfd

+0

@dfd如果您使用实际文本字段并键入文本,则会发生问题。我认为问题是我在UITextViewDelegate方法中实现了该函数。我将在编辑中加入屏幕截图。 – Stefan

回答

1

我认为你应该使用类似的东西(注意我用的文本框,但是可以由相同的的TextView):

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 
    var newString = (textField.text! as NSString).replacingCharacters(in: range, with: string) 
    if !newString.hasPrefix(handle) { 
     newString = "\(handle): \(newString)" 
    } 
    textView.text = newString 

    // Optional font color change for the handle 
    let attributedString = NSMutableAttributedString(string: textView.text!, attributes: [ NSFontAttributeName : generalFont, NSForegroundColorAttributeName: textView.textColor ]); 
    attributedString.addAttribute(NSFontAttributeName, value: anotherFont, range: NSMakeRange(0, handle.characters.count)); 
    textView.attributedText = attributedString 
    return false 
} 

如果范围覆盖字符串的第一个字符(放置的位置),您也可以尝试检查range并拒绝编辑(返回false)。

+0

我喜欢这种方法,但我确实得到它的工作,但它仍然缺乏使用'NSMutableAttributedString()'我认为答案在于设置不同范围的不同属性,但我不确定如何做到这一点。 – Stefan

+0

@Stefan之前'return'添加类似的东西:'让attributedString = NSMutableAttributedString(字符串:textView.text, 属性: NSFontAttributeName:generalFont, NSForegroundColorAttributeName:textView.textColor ]) attributedString.addAttribute(NSFontAttributeName,值:anotherFont,范围:NSMakeRange(0,handle.characters.count)); textView.attributedText = attributedString' –

0

请检查:

funs textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { 

    let myHandle = "Johnny: " 
    let substringRange: NSRange = (textView.text as NSString).range(of: myHandle) 
    if range.location >= substringRange.location && range.location <= substringRange.location + substringRange.length - 1 { 
     return false 
    } 
    return true 
}