I'd like to get the index for the tapped character on a UILabel. I've subclassed a UILabel. In my awakeFromNib() I have this:
layoutManager = NSLayoutManager()
textStorage = NSTextStorage(attributedString: self.attributedText)
textStorage.addLayoutManager(layoutManager)
textContainer = NSTextContainer(size: CGSizeMake(self.frame.size.width, self.frame.size.height))
textContainer.lineFragmentPadding = 0
textContainer.maximumNumberOfLines = self.numberOfLines
textContainer.lineBreakMode = self.lineBreakMode
textContainer.size = self.frame.size
layoutManager.addTextContainer(textContainer)
It is working how I want it to for the first 5 characters of the label, as in I tap the first character and in my touchesEnded I get an index of 0:
var touchedCharacterIndex = layoutManager.characterIndexForPoint(touch.locationInView(self), inTextContainer: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
But when I tap anywhere past the first four characters of the UILabel, I get either 4 or 0, which is incorrect.
Thanks,
Update
From a suggestion in the comments, I've added this:
func updateTextStorage() {
if let attributedText = self.attributedText {
textStorage = NSTextStorage(attributedString: attributedText)
}
textStorage?.addLayoutManager(layoutManager)
textContainer = NSTextContainer(size: CGSizeMake(self.frame.size.width, self.frame.size.height))
textContainer?.lineFragmentPadding = 7
textContainer?.maximumNumberOfLines = self.numberOfLines
textContainer?.lineBreakMode = self.lineBreakMode
textContainer?.size = self.bounds.size
layoutManager.addTextContainer(textContainer!)
layoutManager.textStorage = textStorage
}
I call this in layoutSubviews()
, awakFromNib
and the setters of bounds
, frame
, attributedText
and text
.
And it is now giving me some weird indexes, like if text length is 21, tapping the first letter gives me 6.
I think the issue is stemming from the fact that NSTextContainer lays out text like a UITextView, which means that it will not be vertically centered like a UILabel.
If you run the following piece of code you can see where your glyphs are laying out.
It should show that the glyphs are being laid out at the top of your textContainer.
So wherever you call
will need to be adjusted to take the vertical shift of the UILabel into account.