107

I'm trying to call a number not using specific numbers but a number that is being called in a variable or at least tell it to pull up the number in your phone. This number that is being called in a variable is a number that I retrieved by using a parser or grabbing from a website sql. I made a button trying to call the phone number stored in the variable with a function but to no avail. Anything will help thanks!

    func callSellerPressed (sender: UIButton!){
 //(This is calls a specific number)UIApplication.sharedApplication().openURL(NSURL(string: "tel://######")!)

 // This is the code I'm using but its not working      
 UIApplication.sharedApplication().openURL(NSURL(scheme: NSString(), host: "tel://", path: busPhone)!)

        }
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Thomas Martinez
  • 1,631
  • 3
  • 16
  • 21

25 Answers25

217

Just try:

if let url = NSURL(string: "tel://\(busPhone)") where UIApplication.sharedApplication().canOpenURL(url) {
  UIApplication.sharedApplication().openURL(url)
}

assuming that the phone number is in busPhone.

NSURL's init(string:) returns an Optional, so by using if let we make sure that url is a NSURL (and not a NSURL? as returned by the init).


For Swift 3:

if let url = URL(string: "tel://\(busPhone)"), UIApplication.shared.canOpenURL(url) {
    if #available(iOS 10, *) {
        UIApplication.shared.open(url)
    } else {
        UIApplication.shared.openURL(url)
    }
}

We need to check whether we're on iOS 10 or later because:

'openURL' was deprecated in iOS 10.0

Thomas Müller
  • 15,565
  • 6
  • 41
  • 47
  • this is giving me an error of unresolved identifier 'url' - pointing toward the .openURL(url) Thanks for the help by the way! – Thomas Martinez Dec 02 '14 at 22:22
  • nvm i was missing just a letter. okay so when i push the button nothing happens. here is more info ---------- func parserDidEndDocument(parser: NSXMLParser!){ println(busPhone) drawUpdatedView() } – Thomas Martinez Dec 02 '14 at 22:30
  • 1
    Are you testing this on a phone? I suspect opening a tel:// URL will only work on an actual iPhone, not in the simulator and not on an iPod or iPad. – Thomas Müller Dec 03 '14 at 02:49
  • Yea I'm testing it on an iphone 4s the button clicks but it doesnt pull up the number called by busPhone from a sql server on my phone. When I use the tel:// with a phone number it dials it. – Thomas Martinez Dec 03 '14 at 16:57
  • 3
    Okay I think I know whats the problem but dont know how to fix it. The number that is being pulled from the URL is exactly written like this 123 456-7890 and not like this 1234567890. How do I translate the tel:// to read the URL in the form that it will recognize? – Thomas Martinez Dec 03 '14 at 21:15
  • Pay attention to the following: the code will work on an actual phone, but will not work on the simulator (-canOpenURL: failed for URL: "tel://40505791" - error: "This app is not allowed to query for scheme tel") – Loïs Talagrand Jul 13 '17 at 00:43
  • This works only if you have no spaces in the number, make sure to remove white spaces in the number – Abdul Hannan Oct 11 '17 at 11:54
  • Hi, Is there any way we can detect that user actually press call button. – Paresh. P Apr 29 '19 at 09:15
  • Can anybody update the code for Swift 5 ? I can't find any luck with these and some other answers which I tried. The dialogue won't open up :( – Zahurafzal Mirza Sep 03 '19 at 09:12
  • @ZahurafzalMirza I added an answer updated for Swift 5. – Mahendra Liya May 28 '20 at 12:13
  • How can I catch 'cancel' tap? – Ash Khachatryan Feb 24 '21 at 06:21
  • Don't forget to write this in info.plist LSApplicationQueriesSchemes tel – Nosov Pavel Dec 04 '21 at 17:23
72

A self contained solution in iOS 10, Swift 3 :

private func callNumber(phoneNumber:String) {

  if let phoneCallURL = URL(string: "tel://\(phoneNumber)") {

    let application:UIApplication = UIApplication.shared
    if (application.canOpenURL(phoneCallURL)) {
        application.open(phoneCallURL, options: [:], completionHandler: nil)
    }
  }
}

You should be able to use callNumber("7178881234") to make a call.

Anusha Kottiyal
  • 3,855
  • 3
  • 28
  • 45
Zorayr
  • 23,770
  • 8
  • 136
  • 129
29

Swift 4,

private func callNumber(phoneNumber:String) {

    if let phoneCallURL = URL(string: "telprompt://\(phoneNumber)") {

        let application:UIApplication = UIApplication.shared
        if (application.canOpenURL(phoneCallURL)) {
            if #available(iOS 10.0, *) {
                application.open(phoneCallURL, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
                 application.openURL(phoneCallURL as URL)

            }
        }
    }
}
Alex Nolasco
  • 18,750
  • 9
  • 86
  • 81
Teja
  • 787
  • 7
  • 21
18

Swift 5: iOS >= 10.0

This solution is nil save.

Only works on physical device.

private func callNumber(phoneNumber: String) {
    guard let url = URL(string: "telprompt://\(phoneNumber)"),
        UIApplication.shared.canOpenURL(url) else {
        return
    }
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
grantespo
  • 2,233
  • 2
  • 24
  • 62
15

Swift 3.0 and ios 10 or older

func phone(phoneNum: String) {
    if let url = URL(string: "tel://\(phoneNum)") {
        if #available(iOS 10, *) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(url as URL)
        }
    }
}
Gandom
  • 151
  • 1
  • 2
11

The above answers are partially correct, but with "tel://" there is only one issue. After the call has ended, it will return to the homescreen, not to our app. So better to use "telprompt://", it will return to the app.

var url:NSURL = NSURL(string: "telprompt://1234567891")!
UIApplication.sharedApplication().openURL(url)
Dipen Gajjar
  • 1,338
  • 14
  • 23
  • Apparently this will get your app [rejected](https://stackoverflow.com/questions/29477108/replacing-tel-or-telprompt-to-call) – Tom Knapen Aug 14 '17 at 10:25
11

Swift 3, iOS 10

func call(phoneNumber:String) {
        let cleanPhoneNumber = phoneNumber.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
        let urlString:String = "tel://\(cleanPhoneNumber)"
        if let phoneCallURL = URL(string: urlString) {
            if (UIApplication.shared.canOpenURL(phoneCallURL)) {
                UIApplication.shared.open(phoneCallURL, options: [:], completionHandler: nil)
            }
        }
  }
LuAndre
  • 1,114
  • 12
  • 23
10

Okay I got help and figured it out. Also I put in a nice little alert system just in case the phone number is not valid. My issue was I was calling it right but the number had spaces and unwanted characters such as ("123 456-7890"). UIApplication only works or accepts if your number is ("1234567890"). So you basically remove the space and invalid characters by making a new variable to pull only the numbers. Then calls those numbers with the UIApplication.

func callSellerPressed (sender: UIButton!){
        var newPhone = ""

        for (var i = 0; i < countElements(busPhone); i++){

            var current:Int = i
            switch (busPhone[i]){
                case "0","1","2","3","4","5","6","7","8","9" : newPhone = newPhone + String(busPhone[i])
                default : println("Removed invalid character.")
            }
        }

        if  (busPhone.utf16Count > 1){

        UIApplication.sharedApplication().openURL(NSURL(string: "tel://" + newPhone)!)
        }
        else{
            let alert = UIAlertView()
            alert.title = "Sorry!"
            alert.message = "Phone number is not available for this business"
            alert.addButtonWithTitle("Ok")
                alert.show()
        }
        }
Thomas Martinez
  • 1,631
  • 3
  • 16
  • 21
8

I am using this method in my application and it's working fine. I hope this may help you too.

func makeCall(phone: String) {
    let formatedNumber = phone.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
    let phoneUrl = "tel://\(formatedNumber)"
    let url:NSURL = NSURL(string: phoneUrl)!
    UIApplication.sharedApplication().openURL(url)
}
Ayath Khan
  • 213
  • 2
  • 10
6

Many of the other answers don't work for Swift 5. Below is the code update to Swift 5:

let formattedNumber = phoneNumberVariable.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")

if let url = NSURL(string: ("tel:" + (formattedNumber)!)) {
    if #available(iOS 10.0, *) {
        UIApplication.shared.open(url as URL, options: [:], completionHandler: nil)
    } else {
        UIApplication.shared.openURL(url as URL)
    }
}

PS:

  1. With most of the answers, I wasn't able to get the prompt on the device. The above code was successfully able to display the prompt.
  2. There is no // after tel: like most answers have. And it works fine.
grantespo
  • 2,233
  • 2
  • 24
  • 62
Mahendra Liya
  • 12,912
  • 14
  • 88
  • 114
5

In Swift 3,

if let url = URL(string:"tel://\(phoneNumber)"), UIApplication.shared.canOpenURL(url) {
     UIApplication.shared.openURL(url)
}
Venk
  • 5,949
  • 9
  • 41
  • 52
5

I am using swift 3 solution with number validation

var validPhoneNumber = ""
    phoneNumber.characters.forEach {(character) in
        switch character {
        case "0"..."9":
            validPhoneNumber.characters.append(character)
        default:
            break
        }
    }

    if UIApplication.shared.canOpenURL(URL(string: "tel://\(validNumber)")!){
        UIApplication.shared.openURL(URL(string: "tel://\(validNumber)")!)
    }
Emmett
  • 464
  • 5
  • 11
4

This is an update to @Tom's answer using Swift 2.0 Note - This is the whole CallComposer class I am using.

class CallComposer: NSObject {

var editedPhoneNumber = ""

func call(phoneNumber: String) -> Bool {

    if phoneNumber != "" {

        for i in number.characters {

            switch (i){
                case "0","1","2","3","4","5","6","7","8","9" : editedPhoneNumber = editedPhoneNumber + String(i)
                default : print("Removed invalid character.")
            }
        }

    let phone = "tel://" + editedPhoneNumber
        let url = NSURL(string: phone)
        if let url = url {
            UIApplication.sharedApplication().openURL(url)
        } else {
            print("There was an error")
        }
    } else {
        return false
    }

    return true
 }
}
Michael McKenna
  • 811
  • 1
  • 11
  • 24
4

openURL() has been deprecated in iOS 10. Here is the new syntax:

if let url = URL(string: "tel://\(busPhone)") {
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
Torre Lasley
  • 7,243
  • 3
  • 24
  • 12
4

If your phone number contains spaces, remove them first! Then you can use the accepted answer's solution.

let numbersOnly = busPhone.replacingOccurrences(of: " ", with: "")

if let url = URL(string: "tel://\(numbersOnly)"), UIApplication.shared.canOpenURL(url) {
    if #available(iOS 10, *) {
        UIApplication.shared.open(url)
    } else {
        UIApplication.shared.openURL(url)
    }
}
Display Name
  • 4,502
  • 2
  • 47
  • 63
  • This question now contains 17 answers and is over 3 years old. Why did you feel it necessary to add yet another answer? – Fogmeister Mar 14 '18 at 13:58
  • 1
    Because I didn't understand why it doesn't work if a phone number contains space. Don't be so negative, mister meister! – Display Name Mar 14 '18 at 14:07
  • Definitely understand that. So add a new question explicitly about spaces in numbers and add your own answer to it. There is nothing wrong with asking a question and answering it yourself. (Although, I am pretty certain that question would be closed as a duplicate). – Fogmeister Mar 14 '18 at 14:08
  • 1
    No, it's important to tell people here why the url is not opened: because it's nil, because the phone number contain spaces. What I agree, that this should rather be a comment than an answer. But there are too many comments there. – Display Name Mar 14 '18 at 15:05
  • Did the mention of spaces help you? – Display Name Jun 06 '18 at 11:26
3
func phone(phoneNum: String) {
    if let url = URL(string: "tel://\(phoneNum)") {
        if #available(iOS 10, *) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(url as URL)
        }
    }
}
hussain
  • 769
  • 2
  • 7
  • 24
3

For iOS 10 and above use below code to make a call

let phoneNo = "1234567890"
guard let number = URL(string: "tel://" + phoneNo ) else { return}
UIApplication.shared.open(number, options: [:], completionHandler: nil) 
Yogesh Rathore
  • 147
  • 1
  • 7
2

Swift 3.0 solution:

let formatedNumber = phone.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
print("calling \(formatedNumber)")
let phoneUrl = "tel://\(formatedNumber)"
let url:URL = URL(string: phoneUrl)!
UIApplication.shared.openURL(url)
mazorati
  • 2,031
  • 3
  • 22
  • 22
2

Here's an alternative way to reduce a phone number to valid components using a Scanner

let number = "+123 456-7890"

let scanner = Scanner(string: number)

let validCharacters = CharacterSet.decimalDigits
let startCharacters = validCharacters.union(CharacterSet(charactersIn: "+#"))

var digits: NSString?
var validNumber = ""
while !scanner.isAtEnd {
    if scanner.scanLocation == 0 {
        scanner.scanCharacters(from: startCharacters, into: &digits)
    } else {
        scanner.scanCharacters(from: validCharacters, into: &digits)
    }

    scanner.scanUpToCharacters(from: validCharacters, into: nil)
    if let digits = digits as? String {
        validNumber.append(digits)
    }
}

print(validNumber)

// +1234567890
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
2

For a Swift 3.1 & backwards compatible approach, do this:

@IBAction func phoneNumberButtonTouched(_ sender: Any) {
  if let number = place?.phoneNumber {
    makeCall(phoneNumber: number)
  }
}

func makeCall(phoneNumber: String) {
   let formattedNumber = phoneNumber.components(separatedBy: 
   NSCharacterSet.decimalDigits.inverted).joined(separator: "")

   let phoneUrl = "tel://\(formattedNumber)"
   let url:NSURL = NSURL(string: phoneUrl)!

   if #available(iOS 10, *) {
      UIApplication.shared.open(url as URL, options: [:], completionHandler: 
      nil)
   } else {
     UIApplication.shared.openURL(url as URL)
   }
}
2

For swift 3.0

if let url = URL(string: "tel://\(number)"), UIApplication.shared.canOpenURL(url) {
    if #available(iOS 10, *) {
        UIApplication.shared.open(url)
    } else {
        UIApplication.shared.openURL(url)
    }
}
else {
    print("Your device doesn't support this feature.")
}
Hardik Thakkar
  • 15,269
  • 2
  • 94
  • 81
2

For Swift 4.2 and above

if let phoneCallURL = URL(string: "tel://\(01234567)"), UIApplication.shared.canOpenURL(phoneCallURL)
{
    UIApplication.shared.open(phoneCallURL, options: [:], completionHandler: nil)
}
iHarshil
  • 739
  • 10
  • 22
2
let formatedNumber = phone.components(separatedBy: NSCharacterSet.decimalDigits.inverted).joined(separator: "")
print("calling \(formatedNumber)")
let phoneUrl = "tel://\(formatedNumber)"
let url:URL = URL(string: phoneUrl)!
UIApplication.shared.openURL(url)
  • 2
    While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Rohan Khude May 27 '19 at 10:10
1

Swift 3.0 & iOS 10+

UIApplication.shared.openURL(url) was changed to UIApplication.shared.open(_ url: URL, options:[:], completionHandler completion: nil)

options and completion handler are optional, rendering:

UIApplication.shared.open(url)

https://developer.apple.com/reference/uikit/uiapplication/1648685-open

RLoniello
  • 2,309
  • 2
  • 19
  • 26
-1

To call a phone number in swift, change the url based upon your needs

 if let phoneCallURL = URL(string: "tel://\(phoneNumber)") {
                let application:UIApplication = UIApplication.shared
                if (application.canOpenURL(phoneCallURL)) {
                    application.open(phoneCallURL, options: [:], completionHandler: nil)
                }
            }

To message with phone number

URL(string: "sms://\(phoneNumber)")

To video call using facetime

URL(string: "facetime://\(phoneNumber)")

To open mail app with mail id

URL(string: "mailto:\(mailId)")
Sasinderan N
  • 77
  • 1
  • 3