diff --git a/Example/iOS Example/ViewController.swift b/Example/iOS Example/ViewController.swift index 01596f5..af5924f 100644 --- a/Example/iOS Example/ViewController.swift +++ b/Example/iOS Example/ViewController.swift @@ -23,7 +23,7 @@ class ViewController: UIViewController { let phoneNumberFormatter = DefaultTextInputFormatter(textPattern: "### (###) ###-##-##") let cardNumberFormatter = DefaultTextInputFormatter(textPattern: "XXXX XXXX XXXX XXXX", patternSymbol: "X") let sumFormatter = SumTextInputFormatter(textPattern: "# ###,## $") - let placeholderPhoneNumberFormatter = PlaceholderTextInputFormatter(textPattern: "### (###) ###-##-##") + let placeholderPhoneNumberFormatter = PlaceholderTextInputFormatter(textPattern: "+## (###) ###-##-##") // MARK: - Life Cycle override func viewDidLoad() { @@ -76,8 +76,8 @@ private extension ViewController { phoneNumberField.defaultTextAttributes = convertToNSAttributedStringKeyDictionary([ NSAttributedString.Key.foregroundColor.rawValue: UIColor.white, NSAttributedString.Key.font.rawValue: getFont()]) -// phoneNumberInputController.formatter = phoneNumberFormatter - phoneNumberInputController.formatter = placeholderPhoneNumberFormatter + phoneNumberInputController.formatter = phoneNumberFormatter +// phoneNumberInputController.formatter = placeholderPhoneNumberFormatter phoneNumberField.delegate = phoneNumberInputController } diff --git a/Source/Extensions/String+Extension.swift b/Source/Extensions/String+Extension.swift index 5b14ecf..a99bee1 100644 --- a/Source/Extensions/String+Extension.swift +++ b/Source/Extensions/String+Extension.swift @@ -61,6 +61,14 @@ extension String { return String(self[rangeBegin.. String { + return String(self[self.startIndex..) -> String { + return String(self[range]) + } + func slice(from: Int, length: Int) -> String? { guard from < count, from + length < count else { return nil } let fromIndex = index(startIndex, offsetBy: from) diff --git a/Source/TextFormatter/DefaultFormatters/Formatters/DefaultTextInputFormatter.swift b/Source/TextFormatter/DefaultFormatters/Formatters/DefaultTextInputFormatter.swift index 387f7e4..c894986 100644 --- a/Source/TextFormatter/DefaultFormatters/Formatters/DefaultTextInputFormatter.swift +++ b/Source/TextFormatter/DefaultFormatters/Formatters/DefaultTextInputFormatter.swift @@ -45,13 +45,20 @@ open class DefaultTextInputFormatter: TextInputFormatter { // MARK: - Format input open func formatInput(currentText: String, range: NSRange, replacementString text: String) -> FormattedTextValue { + guard let swiftRange = Range(range, in: currentText) else { return .zero } + let unformattedRange = self.unformattedRange(from: range) + let unformattedRange1 = self.unformattedRange1(currentText: currentText, from: swiftRange) + let oldUnformattedText = (textFormatter.unformat(currentText) ?? "") as NSString let newText = oldUnformattedText.replacingCharacters(in: unformattedRange, with: text) let formattedText = textFormatter.format(newText) ?? "" - let caretOffset = getCorrectedCaretPosition(range: range, replacementString: text) + let caretOffset = getCorrectedCaretPosition( + range: swiftRange, + replacementString: text + ) return FormattedTextValue(formattedText: formattedText, caretBeginOffset: caretOffset) } @@ -75,11 +82,45 @@ open class DefaultTextInputFormatter: TextInputFormatter { return newRange } + func unformattedRange1(currentText: String, from range: Range) -> Range { + let number1 = getNumberOfFormatChars(text: currentText, before: range.lowerBound) + + let number2 = getNumberOfFormatChars(text: currentText, in: range) + + return range + } + + private func getNumberOfFormatChars(text: String, before: String.Index) -> Int { + let textLeftSlice = text.leftSlice(end: before) + let patternLeftSlice = textPattern.leftSlice(limit: textLeftSlice.count) + var result = 0 + for (textSliceChar, patternSliceChar) in zip(textLeftSlice, patternLeftSlice) { + if textSliceChar == patternSliceChar { result += 1 } + } + return result + } + + private func getNumberOfFormatChars(text: String, in range: Range) -> Int { + let textSlice = text.slice(in: range) + let patternSlice = textPattern.slice(in: range) + + return 0 + } + // MARK: - Caret position calculation - private func getCorrectedCaretPosition(range: NSRange, replacementString: String) -> Int { - let offset = caretPositionCorrector.calculateCaretPositionOffset(originalRange: range, replacementFiltered: replacementString) - return offset +// private func getCorrectedCaretPosition(range: NSRange, replacementString: String) -> Int { +// return caretPositionCorrector.calculateCaretPositionOffset( +// originalRange: range, +// replacementFiltered: replacementString +// ) +// } + + private func getCorrectedCaretPosition(range: Range, replacementString: String) -> Int { + return caretPositionCorrector.calculateCaretPositionOffset( + originalRange: range, + replacementText: replacementString + ) } } diff --git a/Source/TextFormatter/DefaultFormatters/Helpers/CaretPositionCorrector.swift b/Source/TextFormatter/DefaultFormatters/Helpers/CaretPositionCorrector.swift index 63d4fca..7bf1cc3 100644 --- a/Source/TextFormatter/DefaultFormatters/Helpers/CaretPositionCorrector.swift +++ b/Source/TextFormatter/DefaultFormatters/Helpers/CaretPositionCorrector.swift @@ -36,6 +36,17 @@ class CaretPositionCorrector { return offset } + func calculateCaretPositionOffset(originalRange range: Range, replacementText: String) -> Int { + var offset = 0 + + if replacementText.isEmpty { + offset = offsetForRemove(lowerBound: range.lowerBound) + } else { + offset = offsetForInsert(lowerBound: range.lowerBound, replacementLength: replacementText.count) + } + return offset + } + /** Find indexes of patterns symbols in range @@ -48,7 +59,10 @@ class CaretPositionCorrector { var indexes: [String.Index] = [] var tempRange = searchRange while let range = textPattern.range( - of: String(patternSymbol), options: .caseInsensitive, range: tempRange, locale: nil) { + of: String(patternSymbol), + options: .caseInsensitive, + range: tempRange + ) { tempRange = range.upperBound.. Int { + let startIndex = textPattern.startIndex + let searchRange = startIndex.. Int { + let startIndex = lowerBound + let searchRange = startIndex..