I am working on an iOS app. In the app, I have a UITextView
where the user should be typing some paragraphs of attributed text. My requirement is to change the style of the next paragraph every time the user hits Enter
.
So, I implemented the following TextView Delegate function:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.typingAttributes = [NSMutableAttributedString.Key.paragraphStyle: self.paragraphStyle]
}
return true
}
The problem is:
The style of next paragraph is changed, but not immediately after hitting Enter. Instead, a new line is returned first with the old style, and when the user hits Enter again, the paragraph style is changed.
Example:
The full code:
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var textView: UITextView!
// Create paragraph styles
let paragraphStyle = NSMutableParagraphStyle()
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
// Create paragraph style
self.paragraphStyle.firstLineHeadIndent = 140
// Create attributed string
let string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
// Create attributed string
let myAttrString = NSMutableAttributedString(string: string, attributes: [:])
// Write it to text view
textView.attributedText = myAttrString
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.typingAttributes = [NSMutableAttributedString.Key.paragraphStyle: self.paragraphStyle]
}
return true
}
}
I think of the way shouldChangeTextIn
works as similar to the way a spell checker or autocorrect works. When you first type a misspelled word, it doesn't get replaced until you press the space bar. Similarly, shouldChangeTextIn
initially acknowledges \n
when you enter it, but the replacement doesn't happen until the following is input initiated.
You can use the textViewDidChange
instance method instead, which is from the same UITextViewDelegate
protocol:
func textViewDidChange(_ textView: UITextView) {
if (textView.text.last == "\n") {
textView.typingAttributes = [NSMutableAttributedString.Key.paragraphStyle: self.paragraphStyle]
}
}