文字列入力(アルファベットと数字を含む)からクリック可能なリンクとして番号を表示する必要があり、その番号をタップすると、iOSコールダイヤラーが開き、その番号をダイヤルする必要があります。

以下は私が現時点で試したことです。番号をタップ可能なもののように見せ、formattedText変数の下に黒い色の通常のデフォルトテキストとしてすべてのテキストを残すために定義されています。

var formattedText: NSAttributedString{
let message = "Hey you can dial up {88 22 333} number for further assistance"
let linkRange = (message as NSString).range(of: fetchNumber) //fetchNumber method returns the content residing inside flower braces..

guard linkRange.location != NSNotFound else {return nil}
let finalString = NSMutableAttributedString(string: message, attributes:[.font: UIFont.scaledFont(from: .baseText16), foregroundColor: .black])
finalString.addAttributes([.foregroundColor: .blue], range: linkRange) 
return finalString 
}

88 22 333上記の機能の出力は次のとおりです。さらに支援が必要な場合は、番号をダイヤルアップできます。

数値をタップ可能にするために、dataDetectorTypeプロパティを有効にしてUITextViewへのこの属性付きテキスト入力を使用してみましたが、機能していません:( UILabel自体または任意の種類のUIKit要素でそれを実現する方法はありますか?よろしくお願いします

dataDetectorTypeプロパティを有効にしてUITextViewへのこの属性付きテキスト入力を使用しようとしましたが、機能しません:( UILabel自体または任意の種類のUIKit要素でそれを実現する方法はありますか?

応答

まず、携帯電話番号をグローバルに宣言する必要があります。

var mobileNo = "88 22 333"

テキストの属性文字列を設定し、タップ可能なラベルを作成します。

func setupLabel() {
    
    let fullString = "Hey you can dial up " + mobileNo + " number for further assistance"
    let strNSString: NSString = fullString as NSString
    let rangeNumber = (strNSString).range(of: mobileNo)
    let attribute = NSMutableAttributedString.init(string: fullString)
    attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.lightGray , range: rangeNumber)
    attribute.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 16), range: rangeNumber)
    lblNumber.attributedText = attribute
    
    //Tap Gesture
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(lblNumberTapped))
    lblNumber.addGestureRecognizer(tapGesture)
    lblNumber.isUserInteractionEnabled = true
}

その後、タップジェスチャのメソッドを宣言します。

//MARK: - TapGesture Click events
@objc func lblNumberTapped(_ gesture: UITapGestureRecognizer) {
    self.view.endEditing(true)
    
    let text = self.lblNumber.text ?? ""
    let recoverMobileNumber = (text as NSString).range(of: mobileNo)

    if gesture.didTapAttributedTextInLabel(label: lblNumber, inRange: recoverMobileNumber) {
        if let callUrl = URL(string: "tel://\(mobileNo)"), UIApplication.shared.canOpenURL(callUrl) {
             UIApplication.shared.open(callUrl)
        }

    }
    

}

タップイベントを検出するには、UITapGestureRecognizer拡張機能が必要です。

extension UITapGestureRecognizer {
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {

    // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
    let layoutManager = NSLayoutManager()
    let textContainer = NSTextContainer(size: CGSize.zero)
    let textStorage = NSTextStorage(attributedString: label.attributedText!)

    // Configure layoutManager and textStorage
    layoutManager.addTextContainer(textContainer)
    
    textStorage.addLayoutManager(layoutManager)

    // Configure textContainer
    textContainer.lineFragmentPadding = 0.0
    textContainer.lineBreakMode = label.lineBreakMode
    textContainer.maximumNumberOfLines = label.numberOfLines
    let labelSize = label.bounds.size
    textContainer.size = labelSize

    // Find the tapped character location and compare it to the specified range
    let locationOfTouchInLabel = self.location(in: label)
    let textBoundingBox = layoutManager.usedRect(for: textContainer)
    //let textBoundingBox = layoutManager.boundingRect(forGlyphRange: targetRange, in: textContainer)
    let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
    let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
    let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

    return NSLocationInRange(indexOfCharacter, targetRange)
}
}