27

I would like to display a phone number in a SwiftUI Text (or any View), and then make it clickable so that it will open the 'Phone'.

Is there a way to do this with SwiftUI, or should I try to wrap a UITextView in SwiftUI and do it the old-fashioned way with NSAttributed string etc?

I've read the documentation for Text in SwiftUI, and couldn't find anything about how to do this. Currently trying to do this in Xcode 11 beta 5.

I've searched 'text' in the SwiftUI API in SwiftUI.h

I've also searched stackoverflow [swiftui] and google with queries like "make phone number/url tappable", "Tappable link/url swiftUI" etc..

Text("123-456-7890")
    .onTapGesture {
    // do something here
}

(text will be Japanese phone number)

nSquid
  • 763
  • 1
  • 8
  • 15

10 Answers10

35

Using iOS 14 / Xcode 12.0 beta 5

Use new link feature in SwiftUI for phone and email links.

    // Link that will open Safari on iOS devices
    Link("Apple", destination: URL(string: "https://www.apple.com")!)
    
    //  Clickable telphone number
    Link("(800)555-1212", destination: URL(string: "tel:8005551212")!)

    //  Clickable Email Address
    Link("apple@me.com", destination: URL(string: "mailto:apple@me.com")!)
    
Steve Dugan
  • 466
  • 4
  • 5
16

Try this,

let strNumber = "123-456-7890"

Button(action: {
    let tel = "tel://"
    let formattedString = tel + strNumber 
    guard let url = URL(string: formattedString) else { return }
    UIApplication.shared.open(url) 
   }) {
   Text("123-456-7890")
}
Ashish
  • 2,977
  • 1
  • 14
  • 32
11

Thanks to Ashish's answer, I found the necessary code I needed to solve this:

In the action inside of the Button - you need to call this method:

UIApplication.shared.open(url)

to actually make the phone call / open a link in a SwiftUI View.

Of course, I didn't understand how to format my phone number at first, which I found in these answers:

How to use openURL for making a phone call in Swift?

Don't forget to add the 'tel://' to the beginning of your string/format it as URL..

The full code of what worked is

Button(action: {

    // validation of phone number not included
    let dash = CharacterSet(charactersIn: "-")

    let cleanString =     
    hotel.phoneNumber!.trimmingCharacters(in: dash)

    let tel = "tel://"
    var formattedString = tel + cleanString
    let url: NSURL = URL(string: formattedString)! as NSURL

    UIApplication.shared.open(url as URL)

}) {
Text(verbatim: hotel.phoneNumber!)
}
nSquid
  • 763
  • 1
  • 8
  • 15
8

KISS answer:

Button("url") {UIApplication.shared.open(URL(string: "https://google.com")!)}
Oded Breiner
  • 28,523
  • 10
  • 105
  • 71
8

From iOS 14, Apple provides us a Link view by default. So, you can just use this,

Link("Anyone can learn Swift", destination: URL(string: "https://ohmyswift.com")!)

For the previous versions of iOS, like iOS 13.0, you still have to use

Button("Anyone can learn Swift") {
   UIApplication.shared.open(URL(string: "https://ohmyswift.com")!)
}
 
Rizwan Ahmed
  • 919
  • 13
  • 19
  • Any way to use Link like the contacts app? i.e. when you long-press the phone number or address, it will offer to copy it for you? – Daniel P Sep 05 '20 at 09:03
7

iOS 15 (beta)

Take advantage of Markdown in SwiftUI, which supports links!

struct ContentView: View {
    var body: some View {
        Text("Call [123-456-7890](tel:1234567890)")
    }
}

Result:

Call 123-456-7890, numbers are highlighted blue

aheze
  • 24,434
  • 8
  • 68
  • 125
2

Make it a Button() with an action, not a Text() with a gesture.

NRitH
  • 13,441
  • 4
  • 41
  • 44
  • To make a statement without proper facts to back it up, I would wonder why you are suggesting this. I am not saying it's not a valid answer, but I have a Text field with a tap gesture and mine works just fine. – Moebius Jul 07 '20 at 12:43
2
Button {

  var cleanNum = selectedItem.phoneNum
  let charsToRemove: Set<Character> = [" ", "(", ")", "-"] // "+" can stay
  cleanNum.removeAll(where: { charsToRemove.contains($0) })
  
  guard let phoneURL = URL(string: "tel://\(cleanNum)") else { return }
  UIApplication.shared.open(phoneURL, options: [:], completionHandler: nil)

} label: {
  // ...
}
luisbunuel
  • 294
  • 3
  • 5
0

Using iOS 14 / Xcode 12.5
I add this in case you wants to use a view.

To make a call by tapping a View

Link(destination: URL(string: "tel:1234567890")!, label: {
  SomeView()
})

To make a call by tapping a String

Link("1234567890", destination: URL(string: "tel:1234567890")!)
Horacio
  • 1,794
  • 1
  • 16
  • 23
0

You can do this way as well if in case you need to log any event on tap of the link :

    struct exampleView: View {

    @SwiftUI.Environment(\.openURL) private var openURL

    var body: some View {
      
        Button {
            if let url = URL(string: "https://www.google.com") {
                openURL(url)
             }
         } label: {
               Text("Link")
                .foregroundColor(Color("EyrusDarkBlue"))
            }

    }


    }
Sajed
  • 1,797
  • 2
  • 7
  • 21