Skip to content

Instantly share code, notes, and snippets.

@ashevin
Last active June 21, 2017 18:16
Show Gist options
  • Save ashevin/3cd4724fa39ae549acd29b007a0a73cd to your computer and use it in GitHub Desktop.
Save ashevin/3cd4724fa39ae549acd29b007a0a73cd to your computer and use it in GitHub Desktop.
import UIKit
import PlaygroundSupport
extension String {
subscript(range: NSRange) -> String? {
guard range.location + range.length <= self.characters.count else {
return nil
}
let r = index(startIndex, offsetBy: range.location)..<index(startIndex, offsetBy: range.location + range.length)
return self[r]
}
subscript(range: CountableRange<Int>) -> String? {
guard range.endIndex <= self.characters.count else {
return nil
}
let r = index(startIndex, offsetBy: range.startIndex)..<index(startIndex, offsetBy: range.endIndex)
return self[r]
}
}
class Tagger: NSObject, UITextFieldDelegate {
var tagStart: Int? = nil
var tagRange: CountableRange<Int>? = nil
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
if textField.text?.characters.count == 1 && range.length == 1 {
tagCancelled()
}
else if tagRange != nil {
if string == " " {
tagCancelled()
}
else if range.location == tagStart {
tagCancelled()
}
else {
tagExtended(to: range.location - range.length)
}
}
else if string == "@" {
if range.location == 0 {
tagStarted(at: range.location)
}
else if let text = textField.text, text.characters.count > 0 {
let sub = text[(range.location - 1)..<range.location]
print("Previous string: \(String(describing: sub))")
if sub == " " {
tagStarted(at: range.location)
}
}
}
print("text: \(string), range: \(NSStringFromRange(range))")
return true
}
func tagStarted(at location: Int) {
tagStart = location
tagRange = location..<(location + 1)
print("Started tag at: \(location), range: \(String(describing: tagRange))")
}
func tagExtended(to location: Int) {
guard let start = tagStart else {
fatalError("This really shouldn't happen")
}
tagRange = start..<(location + 1)
print("Continued tag at: \(location), range: \(String(describing: tagRange))")
}
func tagCancelled() {
tagStart = nil
tagRange = nil
print("Tag cancelled")
}
}
class TextFieldTarget: NSObject {
func setTargetForTextField(tf: UITextField) {
tf.addTarget(self, action: #selector(textFieldChanged(_:)), for: .editingChanged)
}
func textFieldChanged(_ sender: UITextField) {
if let range = t.tagRange, let text = sender.text {
print("text: \(text[range])")
}
}
}
let target = TextFieldTarget()
let t = Tagger()
let tf = UITextField(frame: CGRect(x: 0, y: 100, width: 200, height: 30))
tf.backgroundColor = .gray
tf.textColor = .white
tf.delegate = t
target.setTargetForTextField(tf: tf)
PlaygroundPage.current.liveView = tf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment