Search code examples
swiftnsurluialertcontrolleruiapplicationnsdatadetector

How to get phone number URL from string with random text and a phone number inside


In my iOS application, I have a bunch of alertController messages containing text and one embedded phone number, and I wanted to offer the user the possibility from making the call from an alerControllerAction, and for that I need to be able to extract the phone number from the string dynamically, turn it into a phone number URL and let the old swift guy do its work, and so that's what I did after following about dozen of tuto around NSDataDetector, I came up with this function that for some reason always returns nil in my phoneNumberURL object. Could you guys check it out and tell me if something seems off ?

Here goes nothing :

private func showsHelpMessage() 
{

        let title = Bundle.main.localizedString(forKey: "account.help.popup.title",
                                                value: "",
                                                table: AFPConfig.sharedInstance.kLocalizableTable)

        let message = Bundle.main.localizedString(forKey: "account.help.popup.message",
                                                  value: "",
                                                  table: AFPConfig.sharedInstance.kLocalizableTable)


        var phoneNumber : String = ""
        let detectorType: NSTextCheckingResult.CheckingType = [.phoneNumber]
        do
        {
            let detector = try NSDataDetector(types: detectorType.rawValue)
            let phoneNumberDetected = detector.firstMatch(in: message, options: [], range: NSRange(location: 0, length: message.utf16.count))

            phoneNumber = (phoneNumberDetected?.phoneNumber)!
            phoneNumber = phoneNumber.removeWhitespace() // added this because i noticed the NSURL kept crashing because of the whitespaces between numbers
        }
        catch
        {
            phoneNumber = "+33969390215"
        }

        if let phoneURL = NSURL(string: ("tel://" + phoneNumber))
        {
            let alertAccessibility = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)


            alertAccessibility.addAction(UIAlertAction(title: "Appeler ?", style: .destructive, handler: { (action) in
                UIApplication.shared.open(phoneURL as URL, options: [:], completionHandler: nil)
            }))
            alertAccessibility.addAction(UIAlertAction(title: "Annuler", style: UIAlertAction.Style.cancel, handler: nil))

            self.present(alertAccessibility, animated: true, completion: nil)
        }
    }

Thank you in advance, and cheers!


Solution

  • Addressing the problem of extracting numbers which can't be identified as definitely phone numbers (see comment on my other answer):

    Rather than try to extract a number from the message and hope that it's a phone number and not a distance or a house number, introduce a placeholder (%d) into the localised string and insert the phone number into the message:

    enum LocalPhoneNumbers {
        case reception = 1000
        case helpdesk = 4567
        // etc.
    }
    
    private function showHelpMessage() {
        // "Call the helpdesk on %d"
        let format = Bundle.main.localizedString(forKey: "account.help.popup.message",
                                                  value: "",
                                                  table: AFPConfig.sharedInstance.kLocalizableTable)
    
        let number = LocalPhoneNumbers.helpdesk.rawValue
        let message = String(format: format, number)
        let url = URL(string: "tel://\(number)")
    
        // Code to show alert here...
    
    }