This post is about how to make hyperlink of words in UILabel.
#Purpose
Personal Note
#Development Environment
- OS X El Captain 10.11.2
- Xcode Version 8.0
#Language
Swift 3.0
#Code
@IBOutlet weak var yourLabel: UILabel!
var targetRect: CGRect = CGRect()
// Hyper Link
func setHyperLink(hyperlinkText: String){
let text = "Hello Qiita Hello Law Hello Guys"
yourLabel.backgroundColor = UIColor.clear
yourLabel.textAlignment = .left
let nsText = text as NSString
let linkRange = text.range(of: hyperlinkText)
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.left
let attributedString = NSMutableAttributedString(string: text, attributes: [ NSParagraphStyleAttributeName: style ])
let firstStart = text.distance(from: text.startIndex, to: linkRange!.lowerBound)
let firstLength = hyperlinkText.characters.count
let firstRange = NSMakeRange(firstStart, firstLength)
let boldFontAttribute = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 13.0)]
// all text colour
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.black, range: NSMakeRange(0, nsText.length))
// link colour
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.black, range: firstRange)
attributedString.addAttributes(boldFontAttribute, range: firstRange)
yourLabel.attributedText = attributedString
yourLabel.isUserInteractionEnabled = true
targetRect = getRect(str: yourLabel.attributedText!, range: firstRange, width: yourLabel.frame.width)
yourLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapText(sender:))))
}
func getRect(str: NSAttributedString, range: NSRange, width: CGFloat) -> CGRect {
let storage = NSTextStorage(attributedString: str)
let container = NSTextContainer(size: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude))
let layoutManager = NSLayoutManager()
layoutManager.addTextContainer(container)
storage.addLayoutManager(layoutManager)
container.lineFragmentPadding = 0
let pointer = UnsafeMutablePointer<NSRange>.allocate(capacity: 1)
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: pointer)
return layoutManager.boundingRect(forGlyphRange: pointer.move(), in: container)
}
func tapText(sender: UITapGestureRecognizer) {
if targetRect.contains(sender.location(in: sender.view)) {
// add your action from here
}
}
However, this code is not compatible with Emoji... counting emoji characters is still problematic.