diff --git a/MessageViewController/MessageAutocompleteController.swift b/MessageViewController/MessageAutocompleteController.swift index 806eb38..e535e46 100644 --- a/MessageViewController/MessageAutocompleteController.swift +++ b/MessageViewController/MessageAutocompleteController.swift @@ -233,7 +233,7 @@ public final class MessageAutocompleteController: MessageTextViewListener { preserveTypingAttributes(for: textView) } - public func willChangeRange(textView: MessageTextView, to range: NSRange) { + public func willChangeText(textView: MessageTextView, inRange range: NSRange, to: String) -> Bool { // range.length == 1: Remove single character // range.lowerBound < textView.selectedRange.lowerBound: Ignore trying to delete @@ -248,6 +248,7 @@ public final class MessageAutocompleteController: MessageTextViewListener { if let isAutocomplete = attribute[NSAttributedAutocompleteKey] as? Bool, isAutocomplete { // Remove the autocompleted substring let lowerRange = NSRange(location: 0, length: range.location + 1) + var shouldPreserveTypedText = true textView.attributedText.enumerateAttribute(NSAttributedAutocompleteKey, in: lowerRange, options: .reverse, using: { (_, range, stop) in // Only delete the first found range @@ -258,9 +259,12 @@ public final class MessageAutocompleteController: MessageTextViewListener { textView.selectedRange = NSRange(location: range.location, length: 0) self.textView.textViewDidChange(textView) self.preserveTypingAttributes(for: textView) + shouldPreserveTypedText = false }) + return shouldPreserveTypedText } } + return true } } diff --git a/MessageViewController/MessageTextView.swift b/MessageViewController/MessageTextView.swift index 3399d65..82c9dae 100644 --- a/MessageViewController/MessageTextView.swift +++ b/MessageViewController/MessageTextView.swift @@ -10,7 +10,7 @@ import UIKit public protocol MessageTextViewListener: class { func didChange(textView: MessageTextView) func didChangeSelection(textView: MessageTextView) - func willChangeRange(textView: MessageTextView, to range: NSRange) + func willChangeText(textView: MessageTextView, inRange: NSRange, to: String) -> Bool } open class MessageTextView: UITextView, UITextViewDelegate { @@ -134,8 +134,13 @@ open class MessageTextView: UITextView, UITextViewDelegate { } public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { - enumerateListeners { $0.willChangeRange(textView: self, to: range) } - return true + // If listener changes text then subsequent listeners will probably get incorrect affected range + // and text as they were changed by previous listener. So be careful playing with textView + var shouldChange = true + // if at least one listener changes text and needs to ignore typed text then this method returns + // that just typed text needs to be ignored + enumerateListeners { shouldChange = shouldChange && $0.willChangeText(textView: self, inRange: range, to: text) } + return shouldChange } } diff --git a/MessageViewController/MessageView.swift b/MessageViewController/MessageView.swift index b01beb5..f6434d4 100644 --- a/MessageViewController/MessageView.swift +++ b/MessageViewController/MessageView.swift @@ -336,6 +336,8 @@ public final class MessageView: UIView, MessageTextViewListener { delegate?.selectionDidChange(messageView: self) } - public func willChangeRange(textView: MessageTextView, to range: NSRange) {} + public func willChangeText(textView: MessageTextView, inRange: NSRange, to: String) -> Bool { + return true + } }