Форматирование номера телефона (Swift)

May 27, 2020

Простая, но полезная с точки зрения UX штука - автоматическое форматирование телефонного номера в более читаемый формат. Задача простая: форматирование (в живом режиме) номера телефона из формата "XXXXXXXXXXX" в более красивый "+X (XXX) XXX-XXX".

    /// Format phone number

    /// Usage:

    ///

    ///     print(formatPhoneNumber(number: "12345678901")) // +1 (234) 567-8901

    private func formatPhoneNumber(number: String) -> String {

        let cleanPhoneNumber = number.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

        let mask = "+X (XXX) XXX-XXXX"

        

        var result = ""

        var index = cleanPhoneNumber.startIndex

        for ch in mask where index < cleanPhoneNumber.endIndex {

            if ch == "X" {

                result.append(cleanPhoneNumber[index])

                index = cleanPhoneNumber.index(after: index)

            } else {

                result.append(ch)

            }

        }

        return result

    }

Этот метод можно использовать в textField. В контроллере не забываем делегировать textField, и в UITextFieldDelegate оставим такой метод:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        guard let text = textField.text else { return false }

        let newString = (text as NSString).replacingCharacters(in: range, with: string)

        textField.text = formatPhoneNumber(number: newString)

        return false

}

Как это работает:

  • cleanPhoneNumber - переводит входной number в числовой формат (при попытке ввести буквы, к примеру)
  • mask - маска, она будет разной для разных стран

Если же необходимо получать номер телефона в более удобном, например, для базы данных, формате "XXXXXXXXXXX" (после редактирования в textField), можно использовать следующий метод:

    /// Get unformatted phone number

    /// Usage:

    ///

    ///     print(removeNumberFormat(number: "+1 (234) 567-8901")) // 12345678901

    private func removeNumberFormat(number: String) -> String {

        let digits = CharacterSet.decimalDigits

        var text = ""

        for char in number.unicodeScalars {

            if digits.contains(char) {

                text.append(char.description)

            }

        }

        return text

    }