自定义缓存cell
#import "XMGClearCacheCell.h"
#import
#import
#define XMGCustomCacheFile [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"Custom"]
@implementation XMGClearCacheCell
// 做一些初始化的设置
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 设置cell右边的指示器(用来说明正在处理一些事情)
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[loadingView startAnimating];
self.accessoryView = loadingView;
// 注意1:设置cell默认的文字(如果设置文字之前userInteractionEnabled=NO, 那么文字会自动变成浅灰色,如果先设置cell的默认文字后设置userInteractionEnabled=NO,则文字的颜色是黑色)
self.textLabel.text = @"清除缓存(正在计算缓存大小...)";
// 注意2:在计算完缓存前,禁止点击
self.userInteractionEnabled = NO;
// int age = 10;
// typeof(age) age2 = 10;
// 注意3:__weak指向的对象为空时,会自动指向nil,如果block里面的self是强指针,即使self为要销毁了,block也会强引用它,让它执行完block的内容在为null,但是如果self是__weak,则block不会保住self的命,self直接变为nil
// __weak XMGClearCacheCell * weakSelf = self;
__weak typeof(self) weakSelf = self;
// 在子线程计算缓存大小,主线程刷新UI
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2.0];
// 获得缓存文件夹路径(耗时操作)
unsigned long long size = XMGCustomCacheFile.fileSize;
size += [SDImageCache sharedImageCache].getSize;
// 注意4:如果cell已经销毁了, 就直接返回(判断cell即self是否为nil,要在耗时操作后判断,操作前判断一般不为nil)
if (weakSelf == nil) return;
NSString *sizeText = nil;
if (size >= pow(10, 9)) { // size >= 1GB
sizeText = [NSString stringWithFormat:@"%.2fGB", size / pow(10, 9)];
} else if (size >= pow(10, 6)) { // 1GB > size >= 1MB
sizeText = [NSString stringWithFormat:@"%.2fMB", size / pow(10, 6)];
} else if (size >= pow(10, 3)) { // 1MB > size >= 1KB
sizeText = [NSString stringWithFormat:@"%.2fKB", size / pow(10, 3)];
} else { // 1KB > size
sizeText = [NSString stringWithFormat:@"%zdB", size];
}
// 生成文字
NSString *text = [NSString stringWithFormat:@"清除缓存(%@)", sizeText];
// 回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
// 设置文字
weakSelf.textLabel.text = text;
// 清空右边的指示器
weakSelf.accessoryView = nil;
// 显示右边的箭头
weakSelf.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// 注意5:添加手势监听器后,点击cell就不会调用tableView的DidSelectedRowAtIndexPath方法,所以可以在手势方法监听cell的点击
[weakSelf addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:weakSelf action:@selector(clearCache)]];
// 恢复点击事件(计算完缓存后,才能点击)
weakSelf.userInteractionEnabled = YES;
});
});
}
return self;
}
/**
* 清除缓存
*/
- (void)clearCache
{
// 弹出指示器
[SVProgressHUD showWithStatus:@"正在清除缓存..." maskType:SVProgressHUDMaskTypeBlack];
// 删除SDWebImage的缓存
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
// 删除自定义的缓存
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr removeItemAtPath:XMGCustomCacheFile error:nil];
[mgr createDirectoryAtPath:XMGCustomCacheFile withIntermediateDirectories:YES attributes:nil error:nil];
// 所有的缓存都清除完毕
dispatch_async(dispatch_get_main_queue(), ^{
// 隐藏指示器
[SVProgressHUD dismiss];
// 设置文字
self.textLabel.text = @"清除缓存(0B)";
});
});
}];
}
/**
* 注意6:当cell重新显示到屏幕上时, 也会调用一次layoutSubviews,如果cell不是自定义,在tableView中,cell重新显示到屏幕时会调用tableView的cellForRowAtIndexPath方法,自定义cell时,可以在layoutSubviews中做设置
*/
- (void)layoutSubviews
{
[super layoutSubviews];
// cell重新显示的时候, 继续转圈圈
// 注意7: UIActivityIndicatorView在离开屏幕时,会自动停止,停止后会自动消失,所以再次出现cell的时候,要设置UIActivityIndicatorView开始动画,如果不是自定义cell可以在tableView的cellForRowAtIndexPath方法设置
// 所以,下次重用该cell时,要重新设置 UIActivityIndicatorView的动画
UIActivityIndicatorView *loadingView = (UIActivityIndicatorView *)self.accessoryView;
[loadingView startAnimating];
}
@end
2.在控制器中tableView同时共存多种cell
@implementation XMGSettingViewController
static NSString * const XMGClearCacheCellId = @"XMGClearCacheCell";
static NSString * const XMGSettingCellId = @"XMGSettingCell";
static NSString * const XMGOtherCellId = @"XMGOtherCell";
- (void)viewDidLoad {
[super viewDidLoad];
// 注意1: 一个tableview注册3种cell,根据不同的情况采用不同的cell
[self.tableView registerClass:[XMGClearCacheCell class] forCellReuseIdentifier:XMGClearCacheCellId];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:XMGSettingCellId];
// 注意2: 注册xib描述的cellregisterNib
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGOtherCell class]) bundle:nil] forCellReuseIdentifier:XMGOtherCellId];
}
// 注意3: 当cell将要出现在屏幕时,就会调用该方法,可以做相关设置,如果自定义cell则可以在layoutSubvious做设置
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/**** 一个tableView同时存在多种cell ****/
// 清除缓存cell
if (indexPath.section == 0 && indexPath.row == 0) {
// XMGClearCacheCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGClearCacheCellId];
//
// // cell重新显示的时候, 继续转圈圈
// UIActivityIndicatorView *loadingView = (UIActivityIndicatorView *)cell.accessoryView;
// [loadingView startAnimating];
//
// return cell;
// 注意4: 将cell封装起来,直接返回cell
return [tableView dequeueReusableCellWithIdentifier:XMGClearCacheCellId];
} else if (indexPath.row == 2) {
// XMGOtherCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGOtherCellId];
// cell.data = data;
// return cell;
// 注意4: 将cell封装起来,直接返回cell
return [tableView dequeueReusableCellWithIdentifier:XMGOtherCellId];
}
// 除了上述2种情况的其他cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGSettingCellId];
cell.textLabel.text = [NSString stringWithFormat:@"%zd - %zd", indexPath.section, indexPath.row];
return cell;
}
#pragma mark - 代理方法
// 注意5: 如果自定义cell添加了手势则不会调用该方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 注意6: 判断不同的cell做事情,一般有两种方法:一种是通过判断cell的种类(class),一种是判断cell的indexPath,多种cell的情况下,一般采取前者
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[XMGOtherCell class]]) {
}
// 方法二:
if (indexPath.row == 3){
// doSomething
}
}
当控制器销毁了,如果cell会继续将剩下的程序执行完,无论cell是否销毁了.如果自定义cell的程序中有block,self没有用__weakSelf,则cell要在执行完程序后才会被销毁,执行程序的时候self不为null.
pow(10, 9)是指数表达式,并且计算的数值是浮点数.