2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UILabelのテキストの一部をハイパーリンク化

Posted at

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.

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?