UITableViewCell+HYBMasonryAutoCellHeight.m 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //
  2. // UITableViewCell+HYBMasonryAutoCellHeight.m
  3. // CellAutoHeightDemo
  4. //
  5. // Created by huangyibiao on 15/9/1.
  6. // Copyright © 2015年 huangyibiao. All rights reserved.
  7. //
  8. #import "UITableViewCell+HYBMasonryAutoCellHeight.h"
  9. #import <objc/runtime.h>
  10. #import "UITableView+HYBCacheHeight.h"
  11. NSString *const kHYBCacheUniqueKey = @"kHYBCacheUniqueKey";
  12. NSString *const kHYBCacheStateKey = @"kHYBCacheStateKey";
  13. NSString *const kHYBRecalculateForStateKey = @"kHYBRecalculateForStateKey";
  14. NSString *const kHYBCacheForTableViewKey = @"kHYBCacheForTableViewKey";
  15. const void *s_hyb_lastViewInCellKey = "hyb_lastViewInCellKey";
  16. const void *s_hyb_bottomOffsetToCellKey = "hyb_bottomOffsetToCellKey";
  17. @implementation UITableViewCell (HYBMasonryAutoCellHeight)
  18. #pragma mark - Public
  19. + (CGFloat)hyb_heightForTableView:(UITableView *)tableView config:(HYBCellBlock)config {
  20. UITableViewCell *cell = [tableView.hyb_reuseCells objectForKey:[[self class] description]];
  21. if (cell == nil) {
  22. cell = [[self alloc] initWithStyle:UITableViewCellStyleDefault
  23. reuseIdentifier:nil];
  24. [tableView.hyb_reuseCells setObject:cell forKey:[[self class] description]];
  25. }
  26. if (config) {
  27. config(cell);
  28. }
  29. return [cell private_hyb_heightForTableView:tableView];
  30. }
  31. + (CGFloat)hyb_heightForTableView:(UITableView *)tableView
  32. config:(HYBCellBlock)config
  33. cache:(HYBCacheHeight)cache {
  34. NSAssert(tableView, @"tableView is necessary param");
  35. if (cache) {
  36. NSDictionary *cacheKeys = cache();
  37. NSString *key = cacheKeys[kHYBCacheUniqueKey];
  38. NSString *stateKey = cacheKeys[kHYBCacheStateKey];
  39. NSString *shouldUpdate = cacheKeys[kHYBRecalculateForStateKey];
  40. NSMutableDictionary *stateDict = tableView.hyb_cacheCellHeightDict[key];
  41. NSString *cacheHeight = stateDict[stateKey];
  42. if (tableView.hyb_cacheCellHeightDict.count == 0
  43. || shouldUpdate.boolValue
  44. || cacheHeight == nil) {
  45. CGFloat height = [self hyb_heightForTableView:tableView config:config];
  46. if (stateDict == nil) {
  47. stateDict = [[NSMutableDictionary alloc] init];
  48. tableView.hyb_cacheCellHeightDict[key] = stateDict;
  49. }
  50. [stateDict setObject:[NSString stringWithFormat:@"%lf", height] forKey:stateKey];
  51. return height;
  52. } else if (tableView.hyb_cacheCellHeightDict.count != 0
  53. && cacheHeight != nil
  54. && cacheHeight.integerValue != 0) {
  55. return cacheHeight.floatValue;
  56. }
  57. }
  58. return [self hyb_heightForTableView:tableView config:config];
  59. }
  60. - (void)setHyb_lastViewInCell:(UIView *)hyb_lastViewInCell {
  61. objc_setAssociatedObject(self,
  62. s_hyb_lastViewInCellKey,
  63. hyb_lastViewInCell,
  64. OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  65. }
  66. - (UIView *)hyb_lastViewInCell {
  67. return objc_getAssociatedObject(self, s_hyb_lastViewInCellKey);
  68. }
  69. - (void)setHyb_lastViewsInCell:(NSArray *)hyb_lastViewsInCell {
  70. objc_setAssociatedObject(self,
  71. @selector(hyb_lastViewsInCell),
  72. hyb_lastViewsInCell,
  73. OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  74. }
  75. - (NSArray *)hyb_lastViewsInCell {
  76. return objc_getAssociatedObject(self, _cmd);
  77. }
  78. - (void)setHyb_bottomOffsetToCell:(CGFloat)hyb_bottomOffsetToCell {
  79. objc_setAssociatedObject(self,
  80. s_hyb_bottomOffsetToCellKey,
  81. @(hyb_bottomOffsetToCell),
  82. OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  83. }
  84. - (CGFloat)hyb_bottomOffsetToCell {
  85. NSNumber *valueObject = objc_getAssociatedObject(self, s_hyb_bottomOffsetToCellKey);
  86. if ([valueObject respondsToSelector:@selector(floatValue)]) {
  87. return valueObject.floatValue;
  88. }
  89. return 0.0;
  90. }
  91. #pragma mark - Private
  92. - (CGFloat)private_hyb_heightForTableView:(UITableView *)tableView {
  93. // NSAssert(self.hyb_lastViewInCell != nil
  94. // || self.hyb_lastViewsInCell.count != 0,
  95. // ASLocalizedString(@"您未指定cell排列中最后的视图对象,无法计算cell的高度"));
  96. [self setNeedsUpdateConstraints];
  97. [self updateConstraintsIfNeeded];
  98. [self setNeedsLayout];
  99. [self layoutIfNeeded];
  100. CGFloat rowHeight = 0.0;
  101. for (UIView *bottomView in self.contentView.subviews) {
  102. if (rowHeight < CGRectGetMaxY(bottomView.frame)) {
  103. rowHeight = CGRectGetMaxY(bottomView.frame);
  104. }
  105. }
  106. // if (self.hyb_lastViewInCell) {
  107. // rowHeight = self.hyb_lastViewInCell.frame.size.height + self.hyb_lastViewInCell.frame.origin.y;
  108. // } else {
  109. // for (UIView *view in self.hyb_lastViewsInCell) {
  110. // if (rowHeight < CGRectGetMaxY(view.frame)) {
  111. // rowHeight = CGRectGetMaxY(view.frame);
  112. // }
  113. // }
  114. // }
  115. rowHeight += self.hyb_bottomOffsetToCell;
  116. return rowHeight;
  117. }
  118. @end