UITableView+SCIndexView.m 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #import "UITableView+SCIndexView.h"
  2. #import <objc/runtime.h>
  3. #import "SCIndexView.h"
  4. @interface SCWeakProxy : NSObject
  5. @property (nonatomic, weak) id target;
  6. @end
  7. @implementation SCWeakProxy
  8. @end
  9. @interface UITableView () <SCIndexViewDelegate>
  10. @property (nonatomic, strong) SCIndexView *sc_indexView;
  11. @end
  12. @implementation UITableView (SCIndexView)
  13. #pragma mark - Swizzle Method
  14. + (void)load
  15. {
  16. [self swizzledSelector:@selector(SCIndexView_layoutSubviews) originalSelector:@selector(layoutSubviews)];
  17. }
  18. + (void)swizzledSelector:(SEL)swizzledSelector originalSelector:(SEL)originalSelector
  19. {
  20. Class class = [self class];
  21. Method originalMethod = class_getInstanceMethod(class, originalSelector);
  22. Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
  23. BOOL didAddMethod =
  24. class_addMethod(class,
  25. originalSelector,
  26. method_getImplementation(swizzledMethod),
  27. method_getTypeEncoding(swizzledMethod));
  28. if (didAddMethod) {
  29. class_replaceMethod(class,
  30. swizzledSelector,
  31. method_getImplementation(originalMethod),
  32. method_getTypeEncoding(originalMethod));
  33. } else {
  34. method_exchangeImplementations(originalMethod, swizzledMethod);
  35. }
  36. }
  37. - (void)SCIndexView_layoutSubviews {
  38. [self SCIndexView_layoutSubviews];
  39. if (!self.sc_indexView) {
  40. return;
  41. }
  42. if (self.superview && !self.sc_indexView.superview) {
  43. [self.superview addSubview:self.sc_indexView];
  44. }
  45. else if (!self.superview && self.sc_indexView.superview) {
  46. [self.sc_indexView removeFromSuperview];
  47. }
  48. if (!CGRectEqualToRect(self.sc_indexView.frame, self.frame)) {
  49. self.sc_indexView.frame = self.frame;
  50. }
  51. [self.sc_indexView refreshCurrentSection];
  52. }
  53. #pragma mark - SCIndexViewDelegate
  54. - (void)indexView:(SCIndexView *)indexView didSelectAtSection:(NSUInteger)section
  55. {
  56. if (self.sc_indexViewDelegate && [self.delegate respondsToSelector:@selector(tableView:didSelectIndexViewAtSection:)]) {
  57. [self.sc_indexViewDelegate tableView:self didSelectIndexViewAtSection:section];
  58. }
  59. }
  60. - (NSUInteger)sectionOfIndexView:(SCIndexView *)indexView tableViewDidScroll:(UITableView *)tableView
  61. {
  62. if (self.sc_indexViewDelegate && [self.delegate respondsToSelector:@selector(sectionOfTableViewDidScroll:)]) {
  63. return [self.sc_indexViewDelegate sectionOfTableViewDidScroll:self];
  64. } else {
  65. return SCIndexViewInvalidSection;
  66. }
  67. }
  68. #pragma mark - Public Methods
  69. - (void)sc_refreshCurrentSectionOfIndexView {
  70. [self.sc_indexView refreshCurrentSection];
  71. }
  72. #pragma mark - Private Methods
  73. - (SCIndexView *)createIndexView {
  74. SCIndexView *indexView = [[SCIndexView alloc] initWithTableView:self configuration:self.sc_indexViewConfiguration];
  75. indexView.translucentForTableViewInNavigationBar = self.sc_translucentForTableViewInNavigationBar;
  76. indexView.startSection = self.sc_startSection;
  77. indexView.delegate = self;
  78. return indexView;
  79. }
  80. #pragma mark - Getter and Setter
  81. - (SCIndexView *)sc_indexView
  82. {
  83. return objc_getAssociatedObject(self, @selector(sc_indexView));
  84. }
  85. - (void)setSc_indexView:(SCIndexView *)sc_indexView
  86. {
  87. if (self.sc_indexView == sc_indexView) return;
  88. objc_setAssociatedObject(self, @selector(sc_indexView), sc_indexView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  89. }
  90. - (SCIndexViewConfiguration *)sc_indexViewConfiguration
  91. {
  92. SCIndexViewConfiguration *sc_indexViewConfiguration = objc_getAssociatedObject(self, @selector(sc_indexViewConfiguration));
  93. if (!sc_indexViewConfiguration) {
  94. sc_indexViewConfiguration = [SCIndexViewConfiguration configuration];
  95. }
  96. return sc_indexViewConfiguration;
  97. }
  98. - (void)setSc_indexViewConfiguration:(SCIndexViewConfiguration *)sc_indexViewConfiguration
  99. {
  100. if (self.sc_indexViewConfiguration == sc_indexViewConfiguration) return;
  101. objc_setAssociatedObject(self, @selector(sc_indexViewConfiguration), sc_indexViewConfiguration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  102. }
  103. - (id<SCTableViewSectionIndexDelegate>)sc_indexViewDelegate
  104. {
  105. SCWeakProxy *weakProxy = objc_getAssociatedObject(self, @selector(sc_indexViewDelegate));
  106. return weakProxy.target;
  107. }
  108. - (void)setSc_indexViewDelegate:(id<SCTableViewSectionIndexDelegate>)sc_indexViewDelegate
  109. {
  110. if (self.sc_indexViewDelegate == sc_indexViewDelegate) return;
  111. SCWeakProxy *weakProxy = [SCWeakProxy new];
  112. weakProxy.target = sc_indexViewDelegate;
  113. objc_setAssociatedObject(self, @selector(sc_indexViewDelegate), weakProxy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  114. }
  115. - (BOOL)sc_translucentForTableViewInNavigationBar
  116. {
  117. NSNumber *number = objc_getAssociatedObject(self, @selector(sc_translucentForTableViewInNavigationBar));
  118. return number.boolValue;
  119. }
  120. - (void)setSc_translucentForTableViewInNavigationBar:(BOOL)sc_translucentForTableViewInNavigationBar
  121. {
  122. if (self.sc_translucentForTableViewInNavigationBar == sc_translucentForTableViewInNavigationBar) return;
  123. objc_setAssociatedObject(self, @selector(sc_translucentForTableViewInNavigationBar), @(sc_translucentForTableViewInNavigationBar), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  124. self.sc_indexView.translucentForTableViewInNavigationBar = sc_translucentForTableViewInNavigationBar;
  125. }
  126. - (NSArray<NSString *> *)sc_indexViewDataSource
  127. {
  128. return objc_getAssociatedObject(self, @selector(sc_indexViewDataSource));
  129. }
  130. - (void)setSc_indexViewDataSource:(NSArray<NSString *> *)sc_indexViewDataSource
  131. {
  132. if (self.sc_indexViewDataSource == sc_indexViewDataSource) return;
  133. objc_setAssociatedObject(self, @selector(sc_indexViewDataSource), sc_indexViewDataSource.copy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  134. if (sc_indexViewDataSource.count > 0) {
  135. if (!self.sc_indexView) {
  136. self.sc_indexView = [self createIndexView];
  137. [self.superview addSubview:self.sc_indexView];
  138. }
  139. self.sc_indexView.dataSource = sc_indexViewDataSource.copy;
  140. self.sc_indexView.hidden = NO;
  141. }
  142. else {
  143. self.sc_indexView.hidden = YES;
  144. }
  145. }
  146. - (NSUInteger)sc_startSection {
  147. NSNumber *number = objc_getAssociatedObject(self, @selector(sc_startSection));
  148. return number.unsignedIntegerValue;
  149. }
  150. - (void)setSc_startSection:(NSUInteger)sc_startSection {
  151. if (self.sc_startSection == sc_startSection) return;
  152. objc_setAssociatedObject(self, @selector(sc_startSection), @(sc_startSection), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  153. self.sc_indexView.startSection = sc_startSection;
  154. }
  155. @end