如何在 iOS10中使用 Swift 打电话?

我希望我的应用程序能够呼叫一个特定的号码时,一个按钮被点击。我试过谷歌一下,但是到目前为止 iOS10似乎还没有这样的网站(openURL 已经没有了)。有人能给我举个例子吗?例如:

@IBAction func callPoliceButton(_ sender: UIButton) {
// Call the local Police department
}
118924 次浏览

You can call like this:

 if let url = URL(string: "tel://\(number)") {
UIApplication.shared.openURL(url)
}

For Swift 3+, you can use like

guard let number = URL(string: "tel://" + number) else { return }
UIApplication.shared.open(number)

OR

UIApplication.shared.open(number, options: [:], completionHandler: nil)

Make sure you've scrubbed your phone number string to remove any instances of (, ), -, or space.

if let phoneCallURL:URL = URL(string: "tel:\(strPhoneNumber)") {
let application:UIApplication = UIApplication.shared
if (application.canOpenURL(phoneCallURL)) {
let alertController = UIAlertController(title: "MyApp", message: "Are you sure you want to call \n\(self.strPhoneNumber)?", preferredStyle: .alert)
let yesPressed = UIAlertAction(title: "Yes", style: .default, handler: { (action) in
application.openURL(phoneCallURL)
})
let noPressed = UIAlertAction(title: "No", style: .default, handler: { (action) in


})
alertController.addAction(yesPressed)
alertController.addAction(noPressed)
present(alertController, animated: true, completion: nil)
}
}

Updated for Swift 3:

used below simple lines of code, if you want to make a phone call:

// function defination:

func makeAPhoneCall()  {
let url: NSURL = URL(string: "TEL://1234567890")! as NSURL
UIApplication.shared.open(url as URL, options: [:], completionHandler: nil)
}

// function call: [Used anywhere in your code]

self.makeAPhoneCall()

Note: Please run the app on a real device because it won't work on the simulator.

Task

Make a call with phone number validation

Details

Tested on:

  • Swift 5.2, Xcode 11.4 (11E146)

Solution

// MARK: DataDetector


class DataDetector {


private class func _find(all type: NSTextCheckingResult.CheckingType,
in string: String, iterationClosure: (String) -> Bool) {
guard let detector = try? NSDataDetector(types: type.rawValue) else { return }
let range = NSRange(string.startIndex ..< string.endIndex, in: string)
let matches = detector.matches(in: string, options: [], range: range)
loop: for match in matches {
for i in 0 ..< match.numberOfRanges {
let nsrange = match.range(at: i)
let startIndex = string.index(string.startIndex, offsetBy: nsrange.lowerBound)
let endIndex = string.index(string.startIndex, offsetBy: nsrange.upperBound)
let range = startIndex..<endIndex
guard iterationClosure(String(string[range])) else { break loop }
}
}
}


class func find(all type: NSTextCheckingResult.CheckingType, in string: String) -> [String] {
var results = [String]()
_find(all: type, in: string) {
results.append($0)
return true
}
return results
}


class func first(type: NSTextCheckingResult.CheckingType, in string: String) -> String? {
var result: String?
_find(all: type, in: string) {
result = $0
return false
}
return result
}
}


// MARK: PhoneNumber


struct PhoneNumber {
private(set) var number: String
init?(extractFrom string: String) {
guard let phoneNumber = PhoneNumber.first(in: string) else { return nil }
self = phoneNumber
}


private init (string: String) { self.number = string }


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


static func extractAll(from string: String) -> [PhoneNumber] {
DataDetector.find(all: .phoneNumber, in: string)
.compactMap {  PhoneNumber(string: $0) }
}


static func first(in string: String) -> PhoneNumber? {
guard let phoneNumberString = DataDetector.first(type: .phoneNumber, in: string) else { return nil }
return PhoneNumber(string: phoneNumberString)
}
}


extension PhoneNumber: CustomStringConvertible { var description: String { number } }


// MARK: String extension


extension String {


// MARK: Get remove all characters exept numbers


func onlyDigits() -> String {
let filtredUnicodeScalars = unicodeScalars.filter { CharacterSet.decimalDigits.contains($0) }
return String(String.UnicodeScalarView(filtredUnicodeScalars))
}


var detectedPhoneNumbers: [PhoneNumber] { PhoneNumber.extractAll(from: self) }
var detectedFirstPhoneNumber: PhoneNumber? { PhoneNumber.first(in: self) }
}

Usage

PhoneNumber(extractFrom: "+1-(800)-123-4567")?.makeACall()


PhoneNumber.extractAll(from: "+1-(800)-123-4567 bla bla 1(617)111-22-33").last?.makeACall()


PhoneNumber.first(in: "+1-(800)-123-4567 bla bla 1(617)111-22-33")?.makeACall()


"+1-(800)-123-4567 bla bla 1(617)111-22-33".detectedPhoneNumbers[1].makeACall()
"+1-(800)-123-4567 bla bla 1(617)111-22-33".detectedFirstPhoneNumber?.makeACall()

Full sample

do not forget to paste the solution code here

func test() {
isPhone("blabla")
isPhone("+1(222)333-44-55")
isPhone("+42 555.123.4567")
isPhone("+1-(800)-123-4567")
isPhone("+7 555 1234567")
isPhone("+7(926)1234567")
isPhone("(926) 1234567")
isPhone("+79261234567")
isPhone("926 1234567")
isPhone("9261234567")
isPhone("1234567")
isPhone("123-4567")
isPhone("123-89-01")
isPhone("495 1234567")
isPhone("469 123 45 67")
isPhone("8 (926) 1234567")
isPhone("89261234567")
isPhone("926.123.4567")
isPhone("415-555-1234")
isPhone("650-555-2345")
isPhone("(416)555-3456")
isPhone("202 555 4567")
isPhone("4035555678")
isPhone(" 1 416 555 9292")
isPhone("1(617)111-22-33!")
isPhone("+44 1838 300284")
isPhone("+44 1838 300284, 1 416 555 9292")
isPhone("+44 1838 3d0384, 1 416 555 9292!")
}


private func isPhone(_ string: String) {
let phoneNumbers = PhoneNumber.extractAll(from: string)
let result = !phoneNumbers.isEmpty
print("\(result ? "✅" : "❌") \(string) | detected phones: \(phoneNumbers)")
}

Result

❌ blabla | detected phones: []
✅ +1(222)333-44-55 | detected phones: [+1(222)333-44-55]
✅ +42 555.123.4567 | detected phones: [555.123.4567]
✅ +1-(800)-123-4567 | detected phones: [+1-(800)-123-4567]
✅ +7 555 1234567 | detected phones: [+7 555 1234567]
✅ +7(926)1234567 | detected phones: [+7(926)1234567]
✅ (926) 1234567 | detected phones: [(926) 1234567]
✅ +79261234567 | detected phones: [+79261234567]
✅ 926 1234567 | detected phones: [926 1234567]
✅ 9261234567 | detected phones: [9261234567]
✅ 1234567 | detected phones: [1234567]
✅ 123-4567 | detected phones: [123-4567]
✅ 123-89-01 | detected phones: [123-89-01]
✅ 495 1234567 | detected phones: [495 1234567]
✅ 469 123 45 67 | detected phones: [469 123 45 67]
✅ 8 (926) 1234567 | detected phones: [8 (926) 1234567]
✅ 89261234567 | detected phones: [89261234567]
✅ 926.123.4567 | detected phones: [926.123.4567]
✅ 415-555-1234 | detected phones: [415-555-1234]
✅ 650-555-2345 | detected phones: [650-555-2345]
✅ (416)555-3456 | detected phones: [(416)555-3456]
✅ 202 555 4567 | detected phones: [202 555 4567]
✅ 4035555678 | detected phones: [4035555678]
✅  1 416 555 9292 | detected phones: [1 416 555 9292]
✅ 1(617)111-22-33! | detected phones: [1(617)111-22-33]
✅ +44 1838 300284 | detected phones: [+44 1838 300284]
✅ +44 1838 300284, 1 416 555 9292 | detected phones: [+44 1838 300284, 1 416 555 9292]
✅ +44 1838 3d0384, 1 416 555 9292! | detected phones: [1 416 555 9292]

By mistake my answer was misplaced, please checkout this one: You can use this:

guard let url = URL(string: "tel://\(yourNumber)") else {
return //be safe
}


if #available(iOS 10.0, *) {
UIApplication.shared.open(url)
} else {
UIApplication.shared.openURL(url)
}

We need to check whether we're on iOS 10 or later As 'openURL' was deprecated in iOS 10.0

In Swift 4.2

func dialNumber(number : String) {


if let url = URL(string: "tel://\(number)"),
UIApplication.shared.canOpenURL(url) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler:nil)
} else {
UIApplication.shared.openURL(url)
}
} else {
// add error message here
}
}

Call this like below

dialNumber(number: "+921111111222")

Hope this help.