如何从带有随机文本和内部 phone 数字的字符串中获取 phone 数字 URL
How to get phone number URL from string with random text and a phone number inside
在我的 iOS 应用程序中,我有一堆包含文本和一个嵌入式 phone 号码的 alertController 消息,我想为用户提供从 alerControllerAction 进行调用的可能性,为此,我需要能够动态地从字符串中提取 phone 数字,将其转换为 phone 数字 URL 并让旧的 swift 人完成它的工作,所以这就是我在遵循 NSDataDetector 周围的十二个 tuto 之后所做的事情,我想出了这个函数,由于某种原因,我的 phoneNumberURL 对象中总是 returns nil。你们能检查一下并告诉我是否有问题吗?
这里什么都没有:
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)
}
}
提前致谢,干杯!
您的方法似乎没问题,但我怀疑您的输入数据可能是真正的问题所在。尝试在操场上进行试验:
import Foundation
enum PhoneNumberDetectionError: Error {
case nothingDetected
case noNumberFound
}
func extractPhoneURL(from string: String) throws -> URL? {
let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
guard let detected = detector.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count)) else {
throw PhoneNumberDetectionError.nothingDetected
}
guard let number = detected.phoneNumber else {
throw PhoneNumberDetectionError.noNumberFound
}
let noWhiteSpaces = number.filter { ![=10=].isWhitespace }
return URL(string: "tel://\(noWhiteSpaces)")
}
let strings = [
"This 555–692–7753 is a phone number",
"This 1 555 692 7753 is a phone number",
"This 123 is an incomplete phone number",
"This does not have a phone number",
"This +1 555 692 7753 is a phone number",
]
strings.forEach {
do {
guard let url = try extractPhoneURL(from: [=10=]) else {
print("❌ '\([=10=])' failed to make URL")
return
}
print("✅ '\([=10=])' -> \(url.absoluteString)")
} catch {
print("❌ '\([=10=])' : \(error)")
}
}
如果您认为应该有效的任何内容都得到一个 ❌,那是您的问题。
此外,您在几个地方有一些奇怪的 (
)
:
// Odd combination of optional unwrap and force-unwrap
phoneNumber = (phoneNumberDetected?.phoneNumber)!
// Concise equivalent
phoneNumber = phoneNumberDetected!.phoneNumber
并且:
// The brackets around the string concatenation don't achieve anything
if let phoneURL = NSURL(string: ("tel://" + phoneNumber))
// Better
if let phoneURL = NSURL(string: "tel://" + phoneNumber)
解决提取不能确定为 phone 数字的问题(参见我的其他答案的评论):
与其尝试从消息中提取数字并希望它是一个 phone 数字而不是距离或门牌号,不如在本地化字符串中引入占位符 (%d
) 并在消息中插入 phone 号码:
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...
}
在我的 iOS 应用程序中,我有一堆包含文本和一个嵌入式 phone 号码的 alertController 消息,我想为用户提供从 alerControllerAction 进行调用的可能性,为此,我需要能够动态地从字符串中提取 phone 数字,将其转换为 phone 数字 URL 并让旧的 swift 人完成它的工作,所以这就是我在遵循 NSDataDetector 周围的十二个 tuto 之后所做的事情,我想出了这个函数,由于某种原因,我的 phoneNumberURL 对象中总是 returns nil。你们能检查一下并告诉我是否有问题吗?
这里什么都没有:
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)
}
}
提前致谢,干杯!
您的方法似乎没问题,但我怀疑您的输入数据可能是真正的问题所在。尝试在操场上进行试验:
import Foundation
enum PhoneNumberDetectionError: Error {
case nothingDetected
case noNumberFound
}
func extractPhoneURL(from string: String) throws -> URL? {
let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
guard let detected = detector.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count)) else {
throw PhoneNumberDetectionError.nothingDetected
}
guard let number = detected.phoneNumber else {
throw PhoneNumberDetectionError.noNumberFound
}
let noWhiteSpaces = number.filter { ![=10=].isWhitespace }
return URL(string: "tel://\(noWhiteSpaces)")
}
let strings = [
"This 555–692–7753 is a phone number",
"This 1 555 692 7753 is a phone number",
"This 123 is an incomplete phone number",
"This does not have a phone number",
"This +1 555 692 7753 is a phone number",
]
strings.forEach {
do {
guard let url = try extractPhoneURL(from: [=10=]) else {
print("❌ '\([=10=])' failed to make URL")
return
}
print("✅ '\([=10=])' -> \(url.absoluteString)")
} catch {
print("❌ '\([=10=])' : \(error)")
}
}
如果您认为应该有效的任何内容都得到一个 ❌,那是您的问题。
此外,您在几个地方有一些奇怪的 (
)
:
// Odd combination of optional unwrap and force-unwrap
phoneNumber = (phoneNumberDetected?.phoneNumber)!
// Concise equivalent
phoneNumber = phoneNumberDetected!.phoneNumber
并且:
// The brackets around the string concatenation don't achieve anything
if let phoneURL = NSURL(string: ("tel://" + phoneNumber))
// Better
if let phoneURL = NSURL(string: "tel://" + phoneNumber)
解决提取不能确定为 phone 数字的问题(参见我的其他答案的评论):
与其尝试从消息中提取数字并希望它是一个 phone 数字而不是距离或门牌号,不如在本地化字符串中引入占位符 (%d
) 并在消息中插入 phone 号码:
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...
}