iOS TableView的UITableViewHeaderFooterView自适应高度

  • 结构


    结构图.png

#import "UITableView+LYCacheFooterViewHeight.h"

#import 

NS_ASSUME_NONNULL_BEGIN

@interface UITableView (LYCacheFooterViewHeight)

@property (nonatomic, strong, readonly) NSMutableDictionary *ly_cacheFooterViewHeightDict;

@property (nonatomic, strong, readonly) NSMutableDictionary *ly_reuseFooterViews;

@end

NS_ASSUME_NONNULL_END

#import "UITableView+LYCacheFooterViewHeight.m"

#import "UITableView+LYCacheFooterViewHeight.h"
#import 

static const void *_ly_tableview_cacheFooterViewHeightKey = "_ly_tableview_cacheFooterViewHeightKey";
static const void *_ly_tableview_reuse_footerViews_key = "_ly_tableview_reuse_footerViews_key";

@implementation UITableView (LYCacheFooterViewHeight)

- (NSMutableDictionary *)ly_cacheFooterViewHeightDict {
    
    NSMutableDictionary *dict = objc_getAssociatedObject(self, _ly_tableview_cacheFooterViewHeightKey);
    if (dict == nil) {
        dict = [[NSMutableDictionary alloc] init];
        objc_setAssociatedObject(self,
                                 _ly_tableview_cacheFooterViewHeightKey,
                                 dict,
                                 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    return dict;
    
}

- (NSMutableDictionary *)ly_reuseFooterViews {
    
    NSMutableDictionary *cells = objc_getAssociatedObject(self, _ly_tableview_reuse_footerViews_key);
    if (cells == nil) {
        cells = [[NSMutableDictionary alloc] init];
        objc_setAssociatedObject(self,
                                 _ly_tableview_reuse_footerViews_key,
                                 cells,
                                 OBJC_ASSOCIATION_RETAIN);
    }
    
    return cells;
    
}

@end

#import "UITableViewHeaderFooterView+LYMasonryAutoFooterViewHeight.h"

#import 
#import "UITableView+LYCacheFooterViewHeight.h"

NS_ASSUME_NONNULL_BEGIN

typedef void(^LYFooterViewBlock)(UITableViewHeaderFooterView *sourceView);

typedef NSDictionary *_Nullable(^LYCacheHeight)(void);

FOUNDATION_EXTERN NSString *const kLYCacheUniqueKey;

FOUNDATION_EXTERN NSString *const kLYCacheStateKey;

FOUNDATION_EXTERN NSString *const kLYRecalculateForStateKey;

@interface UITableViewHeaderFooterView (LYMasonryAutoFooterViewHeight)

@property (nonatomic, strong) UIView *ly_lastViewInView;

@property (nonatomic, assign) CGFloat ly_bottomOffsetToView;

+ (CGFloat)ly_heightForTableView:(UITableView *)tableView config:(LYFooterViewBlock)config;

+ (CGFloat)ly_heightForTableView:(UITableView *)tableView
                           config:(LYFooterViewBlock)config
                            cache:(LYCacheHeight)cache;

@end

NS_ASSUME_NONNULL_END

#import "UITableViewHeaderFooterView+LYMasonryAutoFooterViewHeight.m"

#import "UITableViewHeaderFooterView+LYMasonryAutoFooterViewHeight.h"
#import 
#import "UITableView+LYCacheFooterViewHeight.h"

NSString *const kLYCacheUniqueKey = @"kLYCacheUniqueKey";
NSString *const kLYCacheStateKey = @"kLYCacheStateKey";
NSString *const kLYRecalculateForStateKey = @"kLYRecalculateForStateKey";
NSString *const kLYCacheForTableViewKey = @"kLYCacheForTableViewKey";

const void *s_ly_lastViewInCellKey = "ly_lastViewInCellKey";
const void *s_ly_bottomOffsetToCellKey = "ly_bottomOffsetToCellKey";

@implementation UITableViewHeaderFooterView (LYMasonryAutoFooterViewHeight)

#pragma mark - Public
+ (CGFloat)ly_heightForTableView:(UITableView *)tableView config:(LYFooterViewBlock)config {
    UITableViewHeaderFooterView *cell = [tableView.ly_reuseFooterViews objectForKey:[[self class] description]];
    
    if (cell == nil) {
        cell = [[self alloc]initWithReuseIdentifier:nil];
        [tableView.ly_reuseFooterViews setObject:cell forKey:[[self class] description]];
    }
    
    if (config) {
        config(cell);
    }
    
    return [cell private_ly_heightForTableView:tableView];
}

+ (CGFloat)ly_heightForTableView:(UITableView *)tableView
                          config:(LYFooterViewBlock)config
                           cache:(LYCacheHeight)cache {
    if (cache) {
        NSDictionary *cacheKeys = cache();
        NSString *key = cacheKeys[kLYCacheUniqueKey];
        NSString *stateKey = cacheKeys[kLYCacheStateKey];
        NSString *shouldUpdate = cacheKeys[kLYRecalculateForStateKey];
        
        NSMutableDictionary *stateDict = tableView.ly_cacheFooterViewHeightDict[key];
        NSString *cacheHeight = stateDict[stateKey];
        
        if (tableView == nil || tableView.ly_cacheFooterViewHeightDict.count == 0 || shouldUpdate.boolValue || cacheHeight == nil) {
            CGFloat height = [self ly_heightForTableView:tableView config:config];
            
            if (stateDict == nil) {
                stateDict = [[NSMutableDictionary alloc] init];
                tableView.ly_cacheFooterViewHeightDict[key] = stateDict;
            }
            
            [stateDict setObject:[NSString stringWithFormat:@"%lf", height] forKey:stateKey];
            
            return height;
        } else if (tableView.ly_cacheFooterViewHeightDict.count != 0
                   && cacheHeight != nil
                   && cacheHeight.integerValue != 0) {
            return cacheHeight.floatValue;
        }
    }
    
    return [self ly_heightForTableView:tableView config:config];
}

-(void)setLy_lastViewInView:(UIView *)ly_lastViewInView{
    objc_setAssociatedObject(self,
                             s_ly_lastViewInCellKey,
                             ly_lastViewInView,
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(UIView *)ly_lastViewInView{
    return objc_getAssociatedObject(self, s_ly_lastViewInCellKey);
}

- (void)setLy_bottomOffsetToView:(CGFloat)ly_bottomOffsetToView{
    objc_setAssociatedObject(self,
                             s_ly_bottomOffsetToCellKey,
                             @(ly_bottomOffsetToView),
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(CGFloat)ly_bottomOffsetToView{
    NSNumber *valueObject = objc_getAssociatedObject(self, s_ly_bottomOffsetToCellKey);
    
    if ([valueObject respondsToSelector:@selector(floatValue)]) {
        return valueObject.floatValue;
    }
    
    return 0.0;
}

#pragma mark - Private
- (CGFloat)private_ly_heightForTableView:(UITableView *)tableView {
    NSAssert(self.ly_lastViewInView != nil, @"您未指定cell排列中最后一个视图对象,无法计算cell的高度");
    
    [self layoutIfNeeded];
    
    CGFloat rowHeight = self.ly_lastViewInView.frame.size.height + self.ly_lastViewInView.frame.origin.y;
    rowHeight += self.ly_bottomOffsetToView;
    
    return rowHeight;
}

@end

说明

  • 这个工具跟标哥的这个工具
    用法一样的,我是照抄这个工具的

你可能感兴趣的:(iOS TableView的UITableViewHeaderFooterView自适应高度)