如何在SwiftUI中创建可点击的网址/电话号码

27

我想在SwiftUI Text(或任何视图)中显示电话号码,并使其可点击以打开'Phone'。

是否有一种使用SwiftUI实现此功能的方法,或者应该尝试使用UITextView进行包装并以旧方式使用NSAttributed字符串等完成操作?

我已经阅读了SwiftUI文档,但没有找到如何实现此功能。目前正在尝试在Xcode 11 beta 5中实现此操作。

我已经在SwiftUI.h的SwiftUI API中搜索了“text”。

我还在stackoverflow [swiftui]和Google上搜索了类似“使电话号码/ URL可点击”,“Tappable link/url swiftUI”等的查询。

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

(将是日本电话号码的文字)

10个回答

36

使用iOS 14 / Xcode 12.0 beta 5

在SwiftUI中使用新的链接特性来创建电话和电子邮件链接。

    // 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")!)
    

耶,iOS 14!它运作正常。是否有文本消息链接选项? - dwaz
找到了我的问题的答案:Link("(123) 555-1212", destination: URL(string: "imessage:1235551212")!) - dwaz
如果您在同一列表单元格中拥有电子邮件地址和电话号码,该怎么办? - user3194306

16

试一试这个,

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")
}

1
我更新了我的问题。这是一个好的开始,你的答案让我自己找到了解决方法,但它没有包含我所需要的重要信息。 - nSquid
有没有一种方法可以在不占用整个屏幕的情况下进行调用? - Derick Mathews
如果电话号码是较长字符串的一部分怎么办? - Dan Selig

11

感谢Ashish的回答,我找到了解决这个问题所需的必要代码:

在按钮的内部动作中,您需要调用此方法:

UIApplication.shared.open(url)

实际上在SwiftUI视图中打电话/打开链接。

当然,一开始我没有理解如何格式化我的电话号码,后来在这些答案中找到了:

如何在Swift中使用openURL拨打电话?

别忘了在字符串的开头添加'tel://'并将其格式化为URL..

有效代码如下:

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!)
}

2
要使用UIApplication,您需要导入UIKit。是否有一种在没有UIKit的情况下打开外部URL的方法? - CZ54
这段代码对我来说至少不需要任何“import UIkit”语句就可以工作。 - nSquid

8

KISS 的答案:

Button("url") {UIApplication.shared.open(URL(string: "https://google.com")!)}

8
从iOS 14开始,苹果默认提供了一个链接视图(Link View)。因此,您可以直接使用它:
Link("Anyone can learn Swift", destination: URL(string: "https://ohmyswift.com")!)

对于之前的iOS版本,如iOS 13.0,你仍需使用

Button("Anyone can learn Swift") {
   UIApplication.shared.open(URL(string: "https://ohmyswift.com")!)
}
 

有没有办法像联系人应用程序一样使用链接? 例如,当您长按电话号码或地址时,它会提供复制选项? - Daniel P

7

iOS 15(测试版)

在支持链接的SwiftUI中利用Markdown!

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

结果:

拨打123-456-7890,数字被标成蓝色


使用LocalizedStrings时,似乎无法正常工作... - Nico S.
1
很好的选择。我不知道那个。 - Ariel Antonio Fundora

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: {
  // ...
}

2
将其制作为具有操作的Button(),而不是带手势的Text()。最初的回答。

如果没有足够的事实支持,就发表观点,我会想知道你为什么这样建议。我并不是说这不是一个有效的答案,但我有一个带有轻拍手势的文本字段,我的工作正常。 - Moebius

0

使用iOS 14 / Xcode 12.5
我添加这个以防你想使用视图。

通过点击视图来打电话

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

通过点击字符串拨打电话

Link("1234567890", destination: URL(string: "tel:1234567890")!)

0
如果您需要在链接点击时记录任何事件,也可以使用以下方式:
    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"))
            }

    }


    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接