iOS - Swift如何在UILabel中点击链接

5w9g7ksd  于 12个月前  发布在  Swift
关注(0)|答案(6)|浏览(353)

这是我的代码,显示在一个UILabel链接

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textFiled: UITextField!

    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let attrStr = try! NSAttributedString(
            data: "This is a link <a href='http://www.google.com'>google</a>".dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)!,
            options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
            documentAttributes: nil)
        label.attributedText = attrStr
    }

}

正如你可以从图片中看到的,它正确地显示了我只是想要它的链接,但该链接无法点击跳转到Web视图或其他视图。实际上,我需要自定义链接点击事件,我真的没有主意:
1.如何获取链接的URL。
1.如果有多个链接,我需要做什么。
感谢您首先检查此问题。

zed5wv10

zed5wv101#

简短的回答是UILabel不支持打开URL。它可以检测到链接存在,但不会做任何事情。
您可以找到问题解决方案的替代方案,您可以阅读有关here的信息

r7knjye2

r7knjye22#

强烈建议使用UITextView对象,而不是UILabel,但是您可以使用KILabel项目作为UILabel的替代方案。参见https://github.com/Krelborn/KILabel/blob/master/README.md

uklbhaso

uklbhaso3#

这是一个基本的方法为您的需要,我用我们为创建一个可点击的标签

private let linkLabel: UILabel = {
    let label = UILabel()
    label.text = "Link"
    return label
}()

  func setup() {
        linkLabel.isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(openLink))
        linkLabel.addGestureRecognizer(tap)
}

    if let openLink = URL(string: "http://www.apple.com") {
    if UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.open(url, options: [:])
    }
}
nafvub8i

nafvub8i4#

正如Luke所说,UILabels不支持URL。但您可以创建一个按钮,使其看起来像一个标签。去掉背景(使其看起来像文本)并实现按钮的函数以打开webview。可以使用属性化字符串编辑按钮中文本的样式。
当您将按钮添加到UI时,您可能希望使用自定义类而不是默认的uibutton类。
您需要:
1.初始化

- (instancetype)initWithFrame:(CGRect)frame {
   self = [super initWithFrame:frame];
     if (self)
     {
         //call the method to configure the button
         [self configure];
     }
   return self;
 }

1.如果使用属性化字符串,请实现setTitle或setAttributedTitle

- (void) setTitle:(NSString *)title forState:(UIControlState)state
 {
        [super setTitle:title forState:state]
 }

- (void)setAttributedTitle:(NSAttributedString *)title forState:   (UIControlState)state{
            [super setAttributedTitle:title forState:state];
         }

3.配置按钮

-(void) configure{
             //configure the buttons label here 
             //you will want to set no background colour
          }

4.将按钮添加到viewcontroller并将类更改为您创建的自定义类。

bvpmtnay

bvpmtnay5#

对于链接,通常正确的答案是使用UITextView
但我明白,对于简单的用例来说,额外的两个子视图可能会有点重。UILabel子类很好,但是您被限制使用自己的子类。其他答案都依赖于重新创建自己的文本堆栈,希望“模仿”UILabel使用的文本堆栈,尽管当文本开始缩小时,这很快就会失败。
因此,我创建了LinkGestureRecognizerhttps://github.com/stuartjmoore/UILabel-LinkGestureRecognizer)来满足您对UILabel的所有需求。
它就像这样简单:

let label = UILabel()
label.attributedText = // An attributed string with inline link ranges

let linkGestureRecognizer = LinkGestureRecognizer(target: self, action: #selector(handleLinkTap))
label.addGestureRecognizer(linkGestureRecognizer)

@objc func handleLinkTap(_ gestureRecognizer: LinkGestureRecognizer) {
    // handle gestureRecognizer.url in gestureRecognizer.range (UTF-16)
}
p8h8hvxi

p8h8hvxi6#

在Swift 5中,为交互式标签创建一个Class,并将其分配给任何您想要使其可点击的uiLabel URL。它将工作在多行,它会发现,如果标签中的子字符串是URL,并将使其可点击.

import Foundation
import UIKit

@IBDesignable
class LinkUILabel: UILabel {
  
  required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)!
  }
  
  override init(frame: CGRect) {
    super.init(frame: frame)
  }
  
  override var text: String? {
    didSet {
      guard text != nil else { return }
      self.addAttributedString()
    }
  }
  
  // Find the URLs from a string with multiple urls and add attributes
  private func addAttributedString() {
    let labelStr = self.text ?? ""
    guard labelStr != "" else { return }
    let stringArray : [String] = labelStr.split(separator: " ").map { String($0) }
    let attributedString = NSMutableAttributedString(string: labelStr)
    
    for urlStr in stringArray where isValidUrl(urlStr: urlStr) {
      self.isUserInteractionEnabled = true
      self.isEnabled = true
      let startIndices = labelStr.indices(of: urlStr).map { $0.utf16Offset(in: labelStr) }
      for index in startIndices {
        attributedString.addAttribute(.link, value: urlStr, range: NSRange(location: index, length: urlStr.count))
      }
    }
    self.attributedText = attributedString
  }
  
  private func isValidUrl(urlStr: String) -> Bool {
    if let url = NSURL(string: urlStr) {
      return UIApplication.shared.canOpenURL(url as URL)
    }
    return false
  }

  // Triggered when the user lifts a finger.
  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let location = touch.location(in: self)
    
    // Configure NSTextContainer
    let textContainer = NSTextContainer(size: bounds.size)
    textContainer.lineFragmentPadding = 0.0
    textContainer.lineBreakMode = lineBreakMode
    textContainer.maximumNumberOfLines = numberOfLines
    
    // Configure NSLayoutManager and add the text container
    let layoutManager = NSLayoutManager()
    layoutManager.addTextContainer(textContainer)
    
    guard let attributedText = attributedText else { return }
    
    // Configure NSTextStorage and apply the layout manager
    let textStorage = NSTextStorage(attributedString: attributedText)
    textStorage.addAttribute(NSAttributedString.Key.font, value: font!, range: NSMakeRange(0, attributedText.length))
    textStorage.addLayoutManager(layoutManager)
    
    // get the tapped character location
    let locationOfTouchInLabel = location
    
    // account for text alignment and insets
    let textBoundingBox = layoutManager.usedRect(for: textContainer)
    let alignmentOffset: CGFloat = aligmentOffset(for: self)
    
    let xOffset = ((bounds.size.width - textBoundingBox.size.width) * alignmentOffset) - textBoundingBox.origin.x
    let yOffset = ((bounds.size.height - textBoundingBox.size.height) * alignmentOffset) - textBoundingBox.origin.y
    let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - xOffset, y: locationOfTouchInLabel.y - yOffset)
    
    // work out which character was tapped
    let characterIndex = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
    
    let attributeValue = self.attributedText?.attribute(.link, at: characterIndex, effectiveRange: nil)
    if let value = attributeValue {
      if  let url = NSURL(string: value as! String) {
        UIApplication.shared.open(url as URL)
        return
      }
    }
  }
  
  private func aligmentOffset(for label: UILabel) -> CGFloat {
    switch label.textAlignment {
    case .left, .natural, .justified:
      return 0.0
    case .center:
      return 0.5
    case .right:
      return 1.0
    @unknown default:
      return 0.0
    }
  }
}
    • 用法**:在视图控制器中创建一个UILabel,赋值为LinkUILabel
@IBOutlet weak var detailLbl: LinkUILabel!
  detailLbl.text = text

相关问题