From f23c1b09076dad9781daf870a8a4d8a6d87c140f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Viktoras=20Laukevic=CC=8Cius?=
 <viktoras.laukevicius@yahoo.com>
Date: Mon, 2 Apr 2018 20:37:00 +0300
Subject: [PATCH 1/2] Text input customization point allowing to ignore typed
 text

---
 .../MessageAutocompleteController.swift               |  3 ++-
 MessageViewController/MessageTextView.swift           | 11 ++++++++---
 MessageViewController/MessageView.swift               |  4 +++-
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/MessageViewController/MessageAutocompleteController.swift b/MessageViewController/MessageAutocompleteController.swift
index 806eb38..9367014 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
@@ -261,6 +261,7 @@ public final class MessageAutocompleteController: MessageTextViewListener {
                 })
             }
         }
+        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
+    }
 
 }

From 7e391984d0ae869a94183c44c4094e54c2b18f2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Viktoras=20Laukevic=CC=8Cius?=
 <viktoras.laukevicius@yahoo.com>
Date: Mon, 2 Apr 2018 20:38:52 +0300
Subject: [PATCH 2/2] After autocompleted text is removed preceding character
 is not removed

---
 MessageViewController/MessageAutocompleteController.swift | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/MessageViewController/MessageAutocompleteController.swift b/MessageViewController/MessageAutocompleteController.swift
index 9367014..e535e46 100644
--- a/MessageViewController/MessageAutocompleteController.swift
+++ b/MessageViewController/MessageAutocompleteController.swift
@@ -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,7 +259,9 @@ 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