Create tap-able “links” in the NSAttributedString of a UILabel?

前端 未结 30 3225
半阙折子戏
半阙折子戏 2020-11-22 02:07

I have been searching this for hours but I\'ve failed. I probably don\'t even know what I should be looking for.

Many applications have text and in this text are web

30条回答
  •  情书的邮戳
    2020-11-22 02:51

    I found a other solution:

    I find a way to detect the link in a html text that you find from the internet you transform it into nsattributeString with :

    func htmlAttributedString(fontSize: CGFloat = 17.0) -> NSAttributedString? {
                let fontName = UIFont.systemFont(ofSize: fontSize).fontName
                let string = self.appending(String(format: "", fontName, fontSize))
                guard let data = string.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
    
                guard let html = try? NSMutableAttributedString (
                    data: data,
                    options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
                    documentAttributes: nil) else { return nil }
                return html
            }
    

    My method allows you to detect the hyperlink without having to specify them.

    • first you create an extension of the tapgesturerecognizer :

      extension UITapGestureRecognizer {
      func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
          guard let attrString = label.attributedText else {
              return false
          }
      
          let layoutManager = NSLayoutManager()
          let textContainer = NSTextContainer(size: .zero)
          let textStorage = NSTextStorage(attributedString: attrString)
      
          layoutManager.addTextContainer(textContainer)
          textStorage.addLayoutManager(layoutManager)
      
          textContainer.lineFragmentPadding = 0
          textContainer.lineBreakMode = label.lineBreakMode
          textContainer.maximumNumberOfLines = label.numberOfLines
          let labelSize = label.bounds.size
          textContainer.size = labelSize
      
          let locationOfTouchInLabel = self.location(in: label)
          let textBoundingBox = layoutManager.usedRect(for: 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)
      }
      

      }

    then in you view controller you created a list of url and ranges to store all the links and the range that the attribute text contain:

    var listurl : [String] = []
        var listURLRange : [NSRange] = []
    

    to find the URL and the URLRange you can use :

        fun findLinksAndRange(attributeString : NSAttributeString){
            notification.enumerateAttribute(NSAttributedStringKey.link , in: NSMakeRange(0, notification.length), options: [.longestEffectiveRangeNotRequired]) { value, range, isStop in
                        if let value = value {
                            print("\(value) found at \(range.location)")
                            let stringValue = "\(value)"
                            listurl.append(stringValue)
                            listURLRange.append(range)
                        }
                    }
    
                westlandNotifcationLabel.addGestureRecognizer(UITapGestureRecognizer(target : self, action: #selector(handleTapOnLabel(_:))))
    
        }
    

    then you implementing the handle tap :

    @objc func handleTapOnLabel(_ recognizer: UITapGestureRecognizer) {
            for index in 0..

    and here we go!

    I hope this solution help you like it help me.

提交回复
热议问题