1

I'm trying to create aUILabel where certain words are underlined and tapping on them triggers an event. To do so I am following the top answer in this link, however I translated it to Swift : Create tap-able "links" in the NSAttributedString of a UILabel?

Here is my code :

let disclaimerLabel : TTTAttributedLabel = {
    let label = TTTAttributedLabel(frame: CGRectZero)
    label.textColor =  UIColor.whiteColor()
    label.font = UIFont.boldSystemFontOfSize(13)
    label.textAlignment = .Center
    label.numberOfLines = 2
    label.adjustsFontSizeToFitWidth = true
    return label
}()

//Inside viewDidLoad

let attString : NSMutableAttributedString = NSMutableAttributedString(string: "By logging in, you agree to our Privacy Policy and Terms and Conditions.")
    let attributes : NSDictionary = [NSForegroundColorAttributeName : UIColor(red: (0.05), green: (0.4), blue: (0.65), alpha: 1.0), NSUnderlineStyleAttributeName : NSUnderlineStyle.StyleSingle.rawValue]
    attString.setAttributes([NSForegroundColorAttributeName : UIColor.whiteColor()], range: NSMakeRange(0,72))
    attString.setAttributes(attributes as? [String : AnyObject], range: NSMakeRange(31, 15))
    attString.setAttributes(attributes as? [String : AnyObject], range: NSMakeRange(50, 21))
    disclaimerLabel.setText(attString)

    disclaimerLabel.userInteractionEnabled = true
    disclaimerLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleLabelTap)))

    layoutManager = NSLayoutManager()
    textContainer = NSTextContainer(size: CGSizeZero)
    textStorage = NSTextStorage(attributedString: attString)

    layoutManager?.addTextContainer(textContainer!)
    textStorage?.addLayoutManager(layoutManager!)

    textContainer!.lineFragmentPadding = 0.0
    textContainer!.lineBreakMode = disclaimerLabel.lineBreakMode
    textContainer!.maximumNumberOfLines = disclaimerLabel.numberOfLines


}

func handleLabelTap(tapGesture : UITapGestureRecognizer) {
    let locationInLabel : CGPoint = tapGesture.locationInView(tapGesture.view)
    let labelSize : CGSize = tapGesture.view!.bounds.size
    let textBoundingBox : CGRect = (self.layoutManager?.usedRectForTextContainer(self.textContainer!))!
    let textContainerOffset : CGPoint = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
    let locationOfTouchInTextContainer : CGPoint = CGPointMake(locationInLabel.x - textContainerOffset.x, locationInLabel.y - textContainerOffset.y)
    let indexOfChar : NSInteger = (self.layoutManager?.characterIndexForPoint(locationOfTouchInTextContainer, inTextContainer: self.textContainer!, fractionOfDistanceBetweenInsertionPoints: nil))!
    let rangeForPrivacy = NSMakeRange(31, 15)
    let rangeForTerms = NSMakeRange(50, 21)

    if (NSLocationInRange(indexOfChar, rangeForPrivacy)) {
        print("privacy tapped")
        self.performSegueWithIdentifier("showPrivacyPolicy", sender: self)
    }
    else if (NSLocationInRange(indexOfChar, rangeForTerms)) {
        print("terms tapped")
    }
}

Everything works fine for the first line of the label, all taps are recognised as expected, however tapping on the second line of the label (where "and conditions" is) does not trigger any event.

Community
  • 1
  • 1
Alk
  • 5,215
  • 8
  • 47
  • 116

0 Answers0