Guest User

Untitled

a guest
Nov 21st, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.94 KB | None | 0 0
  1. //
  2. // TapableLabel.swift
  3. // AspirinUIKit
  4. //
  5. // Created by HamGuy on 2018/11/21.
  6. //
  7.  
  8. import UIKit
  9.  
  10. public protocol TapableLabelDelegate: NSObjectProtocol {
  11. func tapableLabel(_ label: TapableLabel, didTapUrl url: String, atRange range: NSRange)
  12. }
  13.  
  14. public class TapableLabel: UILabel {
  15.  
  16. private var links: [String: NSRange] = [:]
  17. private(set) var layoutManager = NSLayoutManager()
  18. private(set) var textContainer = NSTextContainer(size: CGSize.zero)
  19. private(set) var textStorage = NSTextStorage() {
  20. didSet {
  21. textStorage.addLayoutManager(layoutManager)
  22. }
  23. }
  24.  
  25. public weak var delegate: TapableLabelDelegate?
  26.  
  27. public override var attributedText: NSAttributedString? {
  28. didSet {
  29. if let attributedText = attributedText {
  30. textStorage = NSTextStorage(attributedString: attributedText)
  31. } else {
  32. textStorage = NSTextStorage()
  33. links = [:]
  34. }
  35. }
  36. }
  37.  
  38. public override var lineBreakMode: NSLineBreakMode {
  39. didSet {
  40. textContainer.lineBreakMode = lineBreakMode
  41. }
  42. }
  43.  
  44. public override var numberOfLines: Int {
  45. didSet {
  46. textContainer.maximumNumberOfLines = numberOfLines
  47. }
  48. }
  49.  
  50.  
  51. public override init(frame: CGRect) {
  52. super.init(frame: frame)
  53. setup()
  54. }
  55.  
  56. public required init?(coder aDecoder: NSCoder) {
  57. super.init(coder: aDecoder)
  58. setup()
  59. }
  60.  
  61. public override func layoutSubviews() {
  62. super.layoutSubviews()
  63. textContainer.size = bounds.size
  64. }
  65.  
  66.  
  67. /// addLinks
  68. ///
  69. /// - Parameters:
  70. /// - text: text of link
  71. /// - url: link url string
  72. public func addLink(_ text: String, withURL url: String) {
  73. guard let theText = attributedText?.string as? NSString else {
  74. return
  75. }
  76.  
  77. let range = theText.range(of: text)
  78.  
  79. guard range.location != NSNotFound else {
  80. return
  81. }
  82.  
  83. links[url] = range
  84. }
  85.  
  86. private func setup() {
  87. isUserInteractionEnabled = true
  88. layoutManager.addTextContainer(textContainer)
  89. textContainer.lineFragmentPadding = 0
  90. textContainer.lineBreakMode = lineBreakMode
  91. textContainer.maximumNumberOfLines = numberOfLines
  92. }
  93.  
  94. public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  95. guard let locationOfTouch = touches.first?.location(in: self) else {
  96. return
  97. }
  98.  
  99. textContainer.size = bounds.size
  100. let indexOfCharacter = layoutManager.glyphIndex(for: locationOfTouch, in: textContainer)
  101.  
  102. for (urlString, range) in links {
  103. if NSLocationInRange(indexOfCharacter, range), let url = URL(string: urlString) {
  104. delegate?.tapableLabel(self, didTapUrl: urlString, atRange: range)
  105. }
  106. }
  107. }
  108. }
Add Comment
Please, Sign In to add comment