Formatting Phone number in Swift

前端 未结 12 1892
天命终不由人
天命终不由人 2020-12-02 09:36

I\'m formatting my textfiled text once the user start typing the phone number into this format type 0 (555) 444 66 77 and it is working fine but once I get the

12条回答
  •  悲&欢浪女
    2020-12-02 09:41

    Swift 3 & 4

    This solution removes any non-numeric characters before applying formatting. It returns nil if the source phone number cannot be formatted according to assumptions.

    Swift 4

    The Swift 4 solution accounts for the deprecation of CharacterView and Sting becoming a collection of characters as the CharacterView is.

    import Foundation
    
    func format(phoneNumber sourcePhoneNumber: String) -> String? {
        // Remove any character that is not a number
        let numbersOnly = sourcePhoneNumber.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
        let length = numbersOnly.count
        let hasLeadingOne = numbersOnly.hasPrefix("1")
    
        // Check for supported phone number length
        guard length == 7 || (length == 10 && !hasLeadingOne) || (length == 11 && hasLeadingOne) else {
            return nil
        }
    
        let hasAreaCode = (length >= 10)
        var sourceIndex = 0
    
        // Leading 1
        var leadingOne = ""
        if hasLeadingOne {
            leadingOne = "1 "
            sourceIndex += 1
        }
    
        // Area code
        var areaCode = ""
        if hasAreaCode {
            let areaCodeLength = 3
            guard let areaCodeSubstring = numbersOnly.substring(start: sourceIndex, offsetBy: areaCodeLength) else {
                return nil
            }
            areaCode = String(format: "(%@) ", areaCodeSubstring)
            sourceIndex += areaCodeLength
        }
    
        // Prefix, 3 characters
        let prefixLength = 3
        guard let prefix = numbersOnly.substring(start: sourceIndex, offsetBy: prefixLength) else {
            return nil
        }
        sourceIndex += prefixLength
    
        // Suffix, 4 characters
        let suffixLength = 4
        guard let suffix = numbersOnly.substring(start: sourceIndex, offsetBy: suffixLength) else {
            return nil
        }
    
        return leadingOne + areaCode + prefix + "-" + suffix
    }
    
    extension String {
        /// This method makes it easier extract a substring by character index where a character is viewed as a human-readable character (grapheme cluster).
        internal func substring(start: Int, offsetBy: Int) -> String? {
            guard let substringStartIndex = self.index(startIndex, offsetBy: start, limitedBy: endIndex) else {
                return nil
            }
    
            guard let substringEndIndex = self.index(startIndex, offsetBy: start + offsetBy, limitedBy: endIndex) else {
                return nil
            }
    
            return String(self[substringStartIndex ..< substringEndIndex])
        }
    }
    

    Swift 3

    import Foundation
    
    func format(phoneNumber sourcePhoneNumber: String) -> String? {
    
        // Remove any character that is not a number
        let numbersOnly = sourcePhoneNumber.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
        let length = numbersOnly.characters.count
        let hasLeadingOne = numbersOnly.hasPrefix("1")
    
        // Check for supported phone number length
        guard length == 7 || (length == 10 && !hasLeadingOne) || (length == 11 && hasLeadingOne) else {
            return nil
        }
    
        let hasAreaCode = (length >= 10)
        var sourceIndex = 0
    
        // Leading 1
        var leadingOne = ""
        if hasLeadingOne {
            leadingOne = "1 "
            sourceIndex += 1
        }
    
        // Area code
        var areaCode = ""
        if hasAreaCode {
            let areaCodeLength = 3
            guard let areaCodeSubstring = numbersOnly.characters.substring(start: sourceIndex, offsetBy: areaCodeLength) else {
                return nil
            }
            areaCode = String(format: "(%@) ", areaCodeSubstring)
            sourceIndex += areaCodeLength
        }
    
        // Prefix, 3 characters
        let prefixLength = 3
        guard let prefix = numbersOnly.characters.substring(start: sourceIndex, offsetBy: prefixLength) else {
            return nil
        }
        sourceIndex += prefixLength
    
        // Suffix, 4 characters
        let suffixLength = 4
        guard let suffix = numbersOnly.characters.substring(start: sourceIndex, offsetBy: suffixLength) else {
            return nil
        }
    
        return leadingOne + areaCode + prefix + "-" + suffix
    }
    
    extension String.CharacterView {
        /// This method makes it easier extract a substring by character index where a character is viewed as a human-readable character (grapheme cluster).
        internal func substring(start: Int, offsetBy: Int) -> String? {
            guard let substringStartIndex = self.index(startIndex, offsetBy: start, limitedBy: endIndex) else {
                return nil
            }
    
            guard let substringEndIndex = self.index(startIndex, offsetBy: start + offsetBy, limitedBy: endIndex) else {
                return nil
            }
    
            return String(self[substringStartIndex ..< substringEndIndex])
        }
    }
    

    Example

    func testFormat(sourcePhoneNumber: String) -> String {
        if let formattedPhoneNumber = format(phoneNumber: sourcePhoneNumber) {
            return "'\(sourcePhoneNumber)' => '\(formattedPhoneNumber)'"
        }
        else {
            return "'\(sourcePhoneNumber)' => nil"
        }
    }
    
    print(testFormat(sourcePhoneNumber: "1 800 222 3333"))
    print(testFormat(sourcePhoneNumber: "18002223333"))
    print(testFormat(sourcePhoneNumber: "8002223333"))
    print(testFormat(sourcePhoneNumber: "2223333"))
    print(testFormat(sourcePhoneNumber: "18002223333444"))
    print(testFormat(sourcePhoneNumber: "Letters8002223333"))
    print(testFormat(sourcePhoneNumber: "1112223333"))
    

    Example Output

    '1 800 222 3333' => '1 (800) 222-3333'
    
    '18002223333' => '1 (800) 222-3333'
    
    '8002223333' => '(800) 222-3333'
    
    '2223333' => '222-3333'
    
    '18002223333444' => nil
    
    'Letters8002223333' => '(800) 222-3333'
    
    '1112223333' => nil
    

提交回复
热议问题