UITextField для номера телефона - PullRequest
48 голосов
/ 07 августа 2009

Мне было интересно, как я могу отформатировать текстовое поле, которое я использую для телефонного номера (например, как страницу «Добавить новый контакт» на iPhone. Когда я вхожу в новый мобильный телефон, например, 1236890987, он форматирует его как (123) 689-0987.) У меня уже есть клавиатура в качестве цифровой клавиатуры.

Ответы [ 24 ]

3 голосов
/ 18 февраля 2016

Вы можете добавить номер телефона, например, 000-000-0000 (10-значный). Пожалуйста, используйте этот код.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField==Phone_TXT)
    {
        if (range.location == 12)
        {
            return NO;
        }

        // Backspace
        if ([string length] == 0)
            return YES;

        if ((range.location == 3) || (range.location == 7))
        {

            NSString *str    = [NSString stringWithFormat:@"%@-",textField.text];
            textField.text   = str;
        }

        return YES;
    }
}
3 голосов
/ 11 апреля 2016

Мое решение для формата + X (XXX) XXX-XXXX. (СВИФТ)

func textFieldDidBeginEditing(textField: UITextField) {
    if (textField == self.mobileField) {
        textField.text = "+"
    }
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if (textField == self.mobileField) {
        let newString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)

        if (newString.characters.count < textField.text?.characters.count && newString.characters.count >= 1) {
            return true                                                         // return true for backspace to work
        } else if (newString.characters.count < 1) {
            return false;                        // deleting "+" makes no sence
        }
        if (newString.characters.count > 17 ) {
           return false;
        }

        let components = newString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)

        let decimalString = components.joinWithSeparator("") as NSString
        let length = decimalString.length

        var index = 0
        let formattedString = NSMutableString()
        formattedString.appendString("+")

        if (length >= 1) {
            let countryCode = decimalString.substringWithRange(NSMakeRange(0, 1))
            formattedString.appendString(countryCode)
            index += 1
        }

        if (length > 1) {
            var rangeLength = 3
            if (length < 4) {
                rangeLength = length - 1
            }
            let operatorCode = decimalString.substringWithRange(NSMakeRange(1, rangeLength))
            formattedString.appendFormat(" (%@) ", operatorCode)
            index += operatorCode.characters.count
        }

        if (length > 4) {
            var rangeLength = 3
            if (length < 7) {
                rangeLength = length - 4
            }
            let prefix = decimalString.substringWithRange(NSMakeRange(4, rangeLength))
            formattedString.appendFormat("%@-", prefix)
            index += prefix.characters.count
        }

        if (index < length) {
            let remainder = decimalString.substringFromIndex(index)
            formattedString.appendString(remainder)
        }

        textField.text = formattedString as String

        if (newString.characters.count == 17) {
            textField.resignFirstResponder()
        }

        return false
    }

    return true
}
2 голосов
/ 13 февраля 2016

Вот мой код Swift 2, слегка локализованный с точки зрения Великобритании.

Будет форматироваться:

+ 11234567890 как +1 (123) 456 7890

+ 33123456789 как +33 1 23 45 67 89

+ 441234123456 как +44 1234 123456 (это было дополнительно локализовано как 01234 123456), потому что мне не нужно видеть код страны для номеров в Великобритании.

Звоните следующим образом:

initInternationalPhoneFormats() //this just needs to be done once

var formattedNo = formatInternationalPhoneNo("+11234567890")

Если у вас есть другие коды стран, форматы или улучшения кода, пожалуйста, сообщите мне.

Наслаждайтесь.

import Cocoa

extension String
{
    //extension from http://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language

    subscript (i: Int) -> Character
    {
        return self[self.startIndex.advancedBy(i)]
    }

}

var phoneNoFormat = [String : String]()
var localCountryCode: String? = "+44"

func initInternationalPhoneFormats() 
{
    if phoneNoFormat.count == 0
    {
         phoneNoFormat["0"] = "+44 #### ######" //local no (UK)
         phoneNoFormat["02"] = "+44 ## #### #####" //local no (UK) London

         phoneNoFormat["+1"] = "+# (###) ###-####" //US and Canada

         phoneNoFormat["+234"] = "+## # ### ####" //Nigeria
         phoneNoFormat["+2348"] = "+## ### ### ####" //Nigeria Mobile

         phoneNoFormat["+31"] = "+## ### ## ## ##" //Netherlands
         phoneNoFormat["+316"] = "+## # ## ## ## ##" //Netherlands Mobile
         phoneNoFormat["+33"] = "+## # ## ## ## ##" //France
         phoneNoFormat["+39"] = "+## ## ########" //Italy
         phoneNoFormat["+392"] = "+## #### #####" //Italy
         phoneNoFormat["+393"] = "+## ### #######" //Italy

         phoneNoFormat["+44"] = "+## #### ######" //United Kingdom
         phoneNoFormat["+442"] = "+## ## #### #####" //United Kingdom London

         phoneNoFormat["+51"] = "+## # ### ####" //Peru
         phoneNoFormat["+519"] = "+## ### ### ###" //Peru Mobile
         phoneNoFormat["+54"] = "+## ### ### ####" //Argentina
         phoneNoFormat["+541"] = "+## ## #### ####" //Argentina
         phoneNoFormat["+549"] = "+## # ### ### ####" //Argentina
         phoneNoFormat["+55"] = "+## (##) ####-####" //Brazil
         phoneNoFormat["+551"] = "+## (##) ####-###" //Brazil Mobile?

         phoneNoFormat["+60"] = "+## # #### ####" //Malaysia
         phoneNoFormat["+6012"] = "+## ## ### ####" //Malaysia Mobile
         phoneNoFormat["+607"] = "+## # ### ####" //Malaysia?
         phoneNoFormat["+61"] = "+## # #### ####" //Australia
         phoneNoFormat["+614"] = "+## ### ### ###" //Australia Mobile
         phoneNoFormat["+62"] = "+## ## #######" //Indonesia
         phoneNoFormat["+628"] = "+## ### ######" //Indonesia Mobile
         phoneNoFormat["+65"] = "+## #### ####" //Singapore

         phoneNoFormat["+90"] = "+## (###) ### ## ##" //Turkey
     }
 }

 func getDiallingCode(phoneNo: String) -> String
 {
     var countryCode = phoneNo
     while countryCode.characters.count > 0 && phoneNoFormat[countryCode] == nil
     {
         countryCode = String(countryCode.characters.dropLast())
     }
     if countryCode == "0"
     {
         return localCountryCode!
     }
     return countryCode
 }


 func formatInternationalPhoneNo(fullPhoneNo: String, localisePhoneNo: Bool = true) -> String
 {
     if fullPhoneNo == ""
     {
         return ""
     }
     initInternationalPhoneFormats()

     let diallingCode = getDiallingCode(fullPhoneNo)

     let localPhoneNo = fullPhoneNo.stringByReplacingOccurrencesOfString(diallingCode, withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)

     var filteredPhoneNo = (localPhoneNo.characters.filter{["0","1","2","3","4","5","6","7","8","9"].contains($0)})
     if filteredPhoneNo[0] == "0"
     {
         filteredPhoneNo.removeFirst()
     }

     let phoneNo:String = diallingCode + String(filteredPhoneNo)

     if let format = phoneNoFormat[diallingCode]
     {
         let formatLength = format.characters.count
         var formattedPhoneNo = [Character]()
         var formatPos = 0
         for char in phoneNo.characters
         {
             while formatPos < formatLength && format[formatPos] != "#" && format[formatPos] != "+"
             {
                 formattedPhoneNo.append(format[formatPos])
                 formatPos++
             }

             if formatPos < formatLength
             {
                 formattedPhoneNo.append(char)
                 formatPos++
             }
             else
             {
                 break
             }
         }
         if localisePhoneNo,
             let localCode = localCountryCode
         {
             return String(formattedPhoneNo).stringByReplacingOccurrencesOfString(localCode + " ", withString: "0", options: NSStringCompareOptions.LiteralSearch, range: nil) //US users need to remove the extra 0
         }
         return String(formattedPhoneNo)
     }
     return String(filteredPhoneNo)
 }
1 голос
/ 16 января 2017

Вот мое решение для телефона формата 05xx xxx xxxx. В начале я установил

phoneTextField.delegate = self
phoneTextField.text = "05" // I don't let user to change it.

Также охватывает случаи копирования / вставки для позиции курсора.

Может быть, это кому-то поможет для разных форматов.

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

    if range.location == 0 || range.location == 1 {
        return false
    }

    var phone = (textField.text! as NSString).replacingCharacters(in: range, with: string)

    if phone.length > 13 {
        return false
    }

    phone = phone.replacingOccurrences(of: " ", with: "")
    if phone.characters.count > 7 {
        phone.insert(" ", at: phone.index(phone.startIndex, offsetBy: 4))
        phone.insert(" ", at: phone.index(phone.startIndex, offsetBy: 8))
    } else if phone.characters.count > 4 {
        phone.insert(" ", at: phone.index(phone.startIndex, offsetBy: 4))
    }

    let text = textField.text
    let stringToStart = text?.substring(to: (text?.index((text?.startIndex)!, offsetBy: range.location))!)

    let stringToStartCount = ((stringToStart?.components(separatedBy: " ").count)! > 1) ? (stringToStart?.components(separatedBy: " ").count)!-1 : 0

    var cursorIndex = range.location + string.length - stringToStartCount

    if cursorIndex > 7 {
        cursorIndex += 2
    } else if cursorIndex > 4 {
        cursorIndex += 1
    }

    textField.text = phone
    textField.selectedTextRange = textField.textRange(from: textField.position(from: textField.beginningOfDocument, offset: cursorIndex)!, to: textField.position(from: textField.beginningOfDocument, offset: cursorIndex)!)

    return false
}
1 голос
/ 12 марта 2013

Надеюсь, то, что я собираюсь сказать, будет полезно для новых людей, программирующих на iOS, как и я. Я сделал то, что предлагает Zingle-Dingle (большое спасибо!). Чтобы помочь новым, вам может помочь код и то, что я перечислю. 1. Вы должны добавить UITextFieldDelegate в заголовочный файл. 2. UITextField должен связать делегата с представлением, в моем случае UIViewController, который является файлом заголовка. 3. UITextField должен быть установлен, т. Е. Yourtextfile.delegate = self, в файле ".m".

1 голос
/ 25 февраля 2016

https://github.com/chebur/CHRTextFieldFormatter работает для меня как шарм.

Копирование / вставка со страницы использования:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.phoneNumberFormatter = [[CHRTextFieldFormatter alloc] initWithTextField:self.phoneNumberTextField mask:[CHRPhoneNumberMask new]];
    self.cardNumberFormatter = [[CHRTextFieldFormatter alloc] initWithTextField:self.cardNumberTextField mask:[CHRCardNumberMask new]];
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == self.phoneNumberTextField) {
        return [self.phoneNumberFormatter textField:textField shouldChangeCharactersInRange:range replacementString:string];
    } else if (textField == self.cardNumberTextField) {
        return [self.cardNumberFormatter textField:textField shouldChangeCharactersInRange:range replacementString:string];
    } else {
        return YES;
    }
}

Также быстро:

override func viewDidLoad() {
    super.viewDidLoad()
    self.phoneNumber.delegate = self
    self.phoneNumberFormatter = CHRTextFieldFormatter(textField: self.phoneNumber, mask:CHRPhoneNumberMask())
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if textField == self.phoneNumber {
        return self.phoneNumberFormatter.textField(textField, shouldChangeCharactersInRange: range, replacementString: string)
    }
    return true
}
1 голос
/ 04 апреля 2017

Обновленный ответ от "iOS Unit" для Swift 3 с форматом + X (XXX) XXX-XXXX:

func textFieldDidBeginEditing(_ textField: UITextField) {
        if (textField == self.phoneTextField) {
            textField.text = "+"
        }
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if (textField == self.phoneTextField) {
            let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)

            if (newString.characters.count < (textField.text?.characters.count)! && newString.characters.count >= 1) {
                return true                                                         // return true for backspace to work
            } else if (newString.characters.count < 1) {
                return false;                        // deleting "+" makes no sence
            }
            if (newString.characters.count > 17 ) {
                return false;
            }

            let components = newString.components(separatedBy: CharacterSet.decimalDigits.inverted)
            let decimalString = components.joined(separator: "") as NSString
            let length = decimalString.length

            var index = 0
            let formattedString = NSMutableString()
            formattedString.append("+")

            if (length >= 1) {
                let countryCode = decimalString.substring(with: NSMakeRange(0, 1))
                formattedString.append(countryCode)
                index += 1
            }

            if (length > 1) {
                var rangeLength = 3
                if (length < 4) {
                    rangeLength = length - 1
                }
                let operatorCode = decimalString.substring(with: NSMakeRange(1, rangeLength))
                formattedString.appendFormat(" (%@) ", operatorCode)
                index += operatorCode.characters.count
            }

            if (length > 4) {
                var rangeLength = 3
                if (length < 7) {
                    rangeLength = length - 4
                }
                let prefix = decimalString.substring(with: NSMakeRange(4, rangeLength))
                formattedString.appendFormat("%@-", prefix)
                index += prefix.characters.count
            }

            if (index < length) {
                let remainder = decimalString.substring(from: index)
                formattedString.append(remainder)
            }

            textField.text = formattedString as String

            if (newString.characters.count == 17) {
                textField.resignFirstResponder()
            }

            return false
        }

        return true
    }
1 голос
/ 08 августа 2009

К сожалению, вы должны сделать это самостоятельно. Приложение контактов использует недокументированные API. По какой-то причине присоединение форматеров ввода к текстовым полям не отображается на iPhone, как на Mac. Не стесняйтесь подать отчет об ошибке улучшения функции.

1 голос
/ 21 ноября 2017

Вы можете использовать эту библиотеку https://github.com/luximetr/AnyFormatKit

Пример

let textInputController = TextInputController()

let textInput = TextInputField() // or TextInputView or any TextInput
textInputController.textInput = textInput // setting textInput

let formatter = TextInputFormatter(textPattern: "### (###) ###-##-##", prefix: "+12")
textInputController.formatter = formatter // setting formatter

Просто установите ваш textField на этот textInputController, и он будет форматировать текст с установленным вами шаблоном.

или

let phoneFormatter = TextFormatter(textPattern: "### (###) ###-##-##")
phoneFormatter.formattedText(from: "+123456789012") // +12 (345) 678-90-12

для формата полной строки

0 голосов
/ 03 декабря 2018

Это мое решение, использующее Swift 4 для форматирования числа типа (123) 689-0987

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let currentText:String = textField.text else {return true}
    if string.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) != nil { return false }
    let newCount:Int = currentText.count + string.count - range.length
    let addingCharacter:Bool = range.length <= 0

    if(newCount == 1){
        textField.text = addingCharacter ? currentText + "(\(string)" : String(currentText.dropLast(2))
        return false
    }else if(newCount == 5){
        textField.text = addingCharacter ? currentText + ") \(string)" : String(currentText.dropLast(2))
        return false
    }else if(newCount == 10){
        textField.text = addingCharacter ? currentText + "-\(string)" : String(currentText.dropLast(2))
        return false
    }

    if(newCount > 14){
        return false
    }

    return true
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...