美文网首页
iOS TableView的UITableViewHeaderF

iOS TableView的UITableViewHeaderF

作者: 邓布利多教授 | 来源:发表于2019-08-06 10:39 被阅读0次
    • 结构


      结构图.png

    #import "UITableView+LYCacheFooterViewHeight.h"

    #import <UIKit/UIKit.h>
    
    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 <objc/runtime.h>
    
    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 <UIKit/UIKit.h>
    #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 <objc/runtime.h>
    #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的UITableViewHeaderF

          本文链接:https://www.haomeiwen.com/subject/ywfidctx.html