How to insert a character at any cursor position in a textField?

I have a textField where I can type numbers (2 333,44) or simple math equations (12+3, 11x3,5). For now I can modify the textField.text with adding a new string only to the end of existing text. If I move cursor to any position inside number it will add a new character only at the end: https://i.stack.imgur.com/HzaA9.gif

How to modify the code to insert new characters at any cursor position?

My current code from shouldChangeCharactersIn:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.maximumFractionDigits = 2
    formatter.minimumFractionDigits = 1
    formatter.locale = .current
    formatter.roundingMode = .down
    
    let numberString = "\(textField.text ?? "")".replacingOccurrences(of: formatter.groupingSeparator, with: "")
    let lastCharacter = numberString.last ?? "."
    var symbol: String {
        var tempArray = [String]()
        let mathSymbols = "+-÷x"
        for character in numberString {
            if mathSymbols.contains(character) {
                tempArray.append(String(character))
            }
        }
        return tempArray.last ?? ""
    }
    var numbersArray: [String] {
        if numberString.first == "-" {
            let positiveString = numberString.dropFirst()
            var tempArray = positiveString.components(separatedBy: symbol)
            tempArray[0] = "-\(tempArray[0])"
            return tempArray
        } else {
            return numberString.components(separatedBy: symbol)
        }
    }
    //turn numbers into Float and create a String from them to be able to receive a correct result from NSExpression
    var floatNumberArray: [Float] {
        if numberString.first == "-" {
            let tempString = lastCharacter == Character(formatter.decimalSeparator) ? numberString.dropFirst().dropLast() : numberString.dropFirst()
            var tempArray = tempString.components(separatedBy: symbol)
            tempArray[0] = "-\(tempArray[0])"
            return tempArray.compactMap { Float($0.replacingOccurrences(of: formatter.decimalSeparator, with: ".")) }
        } else {
            return numberString.components(separatedBy: symbol).compactMap { Float($0.replacingOccurrences(of: formatter.decimalSeparator, with: ".")) }
        }
    }
    
    var floatNumberString: String {
        if numberString.contains("x") {
            return "\(floatNumberArray.first ?? 0)\("*")\(floatNumberArray.last ?? 0)"
        } else if numberString.contains("÷") {
            return "\(floatNumberArray.first ?? 0)\("/")\(floatNumberArray.last ?? 0)"
        } else {
            return "\(floatNumberArray.first ?? 0)\(symbol)\(floatNumberArray.last ?? 0)"
        }
    }
    
    let amountOfDecimals = "\(numbersArray.last ?? "")\(string)".filter({ $0 == Character(formatter.decimalSeparator) }).count
    
    //allow to insert 0 after the decimal symbol to avoid formatting i.e. 2.04
    formatter.minimumFractionDigits = numberString.last == Character(formatter.decimalSeparator) && string == "0" ? 1 : 0
    
    //allow string to be modified by backspace button
    if string == "" { return false }
    
    //allow numbers as a first character, except math symbols
    if numberString == "" {
        if Character(string).isNumber {
            textField.text = string
        } else {
            return false
        }
    }
    //allow only one decimal symbol per number
    else if amountOfDecimals > 1 { return false }
     
    if numbersArray.count > 1 {
    //if number is entered
        if Character(string).isNumber {
            textField.text = "\(formatter.string(for: Double("\(numbersArray.first?.replacingOccurrences(of: formatter.decimalSeparator, with: ".") ?? "")") ?? 0) ?? "")\(symbol)\(formatter.string(for: Double("\(numbersArray.last?.replacingOccurrences(of: formatter.decimalSeparator, with: ".") ?? "")\(string)") ?? 0) ?? "")"
    //if symbol is entered
        } else if string == formatter.decimalSeparator {
            textField.text = "\(textField.text ?? "")\(string)"
        } else {
    //perform calculation if last entered character is a number
            if lastCharacter.isNumber {
                let result = performCalculation(format: floatNumberString)
                textField.text = string == "=" ? "\(formatter.string(from: result) ?? "")" : "\(formatter.string(from: result) ?? "")\(string)"
    //perform calculation if last entered character is a decimal symbol
            } else if lastCharacter == Character(formatter.decimalSeparator) {
                let result = performCalculation(format: floatNumberString)
                textField.text = string == "=" ? "\(formatter.string(from: result) ?? "")" : "\(formatter.string(from: result) ?? "")\(string)"
    //change math symbol before enter a second number
            } else {
                textField.text = "\(textField.text?.dropLast() ?? "")\(string)"
            }
        }
    } else {
    //if number is entered
        if Character(string).isNumber {
            textField.text = "\(formatter.string(for: Double("\(numbersArray.first?.replacingOccurrences(of: formatter.decimalSeparator, with: ".") ?? "")\(string)") ?? 0) ?? "")"
        } else {
    //if math symbol is entered
            if lastCharacter.isNumber {
                textField.text = "\(textField.text ?? "")\(string)"
            }
        }
    }
    return false
}

func performCalculation(format: String) -> NSNumber {
    let expression = NSExpression(format: format)
    let answer = expression.expressionValue(with: nil, context: nil)
    return answer as! NSNumber
}
}

My guess is to modify the string with a range. So I tried:

1.Create range

    let numberString = "\(textField.text ?? "")".replacingOccurrences(of: formatter.groupingSeparator, with: "")
    guard let range = Range(range, in: numberString) else { return false }

2.Remove string at the end and use range instead

        } else {
    //if number is entered
        if Character(string).isNumber {
            textField.text = "\(formatter.string(for: Double("\(numbersArray.first?.replacingOccurrences(of: formatter.decimalSeparator, with: ".").replacingCharacters(in: range, with: string) ?? "") ?? "")") ?? 0) ?? "")"
        } else {
    //if math symbol is entered
            if lastCharacter.isNumber {
                textField.text = "\(textField.text?.replacingCharacters(in: range, with: string) ?? "") ?? "")"
            }
        }
    }
    return false
}

3.Then I can insert at any position but can add only 4 numbers if add from keyboard and insert more from another cursor position: https://i.stack.imgur.com/iDV4n.gif

Test project on GitHub

How to insert a character at any cursor position in a textField?
 
 
Q