-
结构
结构图.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
网友评论