session-ios/Signal/src/util/TextFieldHelper.swift
2018-05-30 15:05:02 -04:00

56 lines
2.1 KiB
Swift

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import UIKit
@objc public class TextFieldHelper: NSObject {
// Used to implement the UITextFieldDelegate method: `textField:shouldChangeCharactersInRange:replacementString`
// Takes advantage of Swift's superior unicode handling to append partial pasted text without splitting multi-byte characters.
@objc public class func textField(_ textField: UITextField, shouldChangeCharactersInRange editingRange: NSRange, replacementString: String, byteLimit: UInt) -> Bool {
let byteLength = { (string: String) -> UInt in
return UInt(string.utf8.count)
}
let existingString = textField.text ?? ""
// Given an NSRange, we need to interact with the NS flavor of substring
let removedString = (existingString as NSString).substring(with: editingRange)
let lengthOfRemainingExistingString = byteLength(existingString) - byteLength(removedString)
let newLength = lengthOfRemainingExistingString + byteLength(replacementString)
if (newLength <= byteLimit) {
return true
}
// Don't allow any change if inserting a single char is already over the limit (typically this means typing)
if (replacementString.count < 2) {
return false
}
// However if pasting, accept as much of the string as possible.
let availableSpace = byteLimit - lengthOfRemainingExistingString
var acceptableSubstring = ""
for (_, char) in replacementString.enumerated() {
var maybeAcceptableSubstring = acceptableSubstring
maybeAcceptableSubstring.append(char)
if (byteLength(maybeAcceptableSubstring) <= availableSpace) {
acceptableSubstring = maybeAcceptableSubstring
} else {
break
}
}
textField.text = (existingString as NSString).replacingCharacters(in: editingRange, with: acceptableSubstring)
// We've already handled any valid editing manually, so prevent further changes.
return false
}
}