项目实战No4 清除缓存

一 cell设置

  • cell数据
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    XMGMeCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGMeCellId];

    if (indexPath.section == 0) {
        cell.textLabel.text = @"登录/注册";
        cell.imageView.image = [UIImage imageNamed:@"setup-head-default"];
    } else {
        cell.textLabel.text = @"离线下载";
    }

    return cell;
}
  • 每组的间距调整
  self.tableView.sectionHeaderHeight = 0;
  self.tableView.sectionFooterHeight = 10;
  • cell距离页面头部间隙过大,重写setFrame
    • 通过frame.origin.y -= 25实现cell上移,但是整体不会上移,不建议这么做
    • 通过设置内边距:
// 设置内边距(-25代表:所有内容往上移动25)
    self.tableView.contentInset = UIEdgeInsetsMake(-25, 0, 0, 0);
  • 自定义cell初始化,cell创建时调用一次
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        self.textLabel.textColor = [UIColor darkGrayColor];

        // 设置背景图片
        self.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mainCellBackground"]];
    }
    return self;
}
  • 图片拉伸设置
    这里写图片描述

  • 调整image和label间距

    • 问题:下面label也会跟着调整,需要增加判断
- (void)layoutSubviews
{
    [super layoutSubviews];

    if (self.imageView.image == nil) return;

    // 调整imageView
    self.imageView.y = XMGCommonMargin * 0.5;
    self.imageView.height = self.contentView.height - 2 * self.imageView.y;
    self.imageView.width = self.imageView.height;

    // 调整Label
    self.textLabel.x = CGRectGetMaxX(self.imageView.frame) + XMGCommonMargin;
    //  self.textLabel.x = self.imageView.x + self.imageView.width + XMGCommonMargin;
   // 另一种写法 :
    //   CGRectGetMaxX(self.imageView.frame) == self.imageView.x + self.imageView.width
    //   CGRectGetMinX(self.imageView.frame) == self.imageView.x
    //   CGRectGetMidX(self.imageView.frame) == self.imageView.x + self.imageView.width * 0.5
    //   CGRectGetMidX(self.imageView.frame) == self.imageView.centerX
}

二 加载方块数据

  • 自定义Footer,重写initWithFrame
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        // 请求参数
        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        params[@"a"] = @"square";
        params[@"c"] = @"topic";

        // 发送请求
        XMGWeakSelf;
    [[AFHTTPSessionManager manager] GET:RequestURL parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
    [weakSelf createSquares:[NBSquare objectArrayWithKeyValuesArray:responseObject[@"square_list"]]];
     } failure:^(NSURLSessionDataTask *task, NSError *error) {

        }];
    }
    return self;
}
  • 需要3个属性,建一个modal
@interface NBSquare : NSObject
/** 名字 */
@property (nonatomic, copy) NSString *name;
/** 图标 */
@property (nonatomic, copy) NSString *icon;
/** 链接 */
@property (nonatomic, copy) NSString *url;
@end
  • 九宫格方块实现
/**
 * 创建方块
 */
- (void)createSquares:(NSArray *)squares
{
    // 每行的列数
    int colsCount = 4;

    // 按钮尺寸
    CGFloat buttonW = self.width / colsCount;
    CGFloat buttonH = buttonW;

    // 遍历所有的模型
    NSUInteger count = squares.count;
    for (NSUInteger i = 0; i < count; i++) {
        // 创建按钮
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button];

        // frame
        CGFloat buttonX = (i % colsCount) * buttonW;
        CGFloat buttonY = (i / colsCount) * buttonH;
        button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
   }
}
  • 设置数据
// 设置题目
[button setTitle:square.name forState:UIControlStateNormal];

注意:设置图片,不只拿到image就行,需要用set…forState记录状态;

  • 下载图片方法1:
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:square.icon] options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
    [button setImage:image forState:UIControlStateNormal];
}];
  • 下载图片方法2:
[button sd_setImageWithURL:[NSURL URLWithString:square.icon] forState:UIControlStateNormal];
  • 子控件button重新布局
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        self.titleLabel.textAlignment = NSTextAlignmentCenter;
        self.titleLabel.font = [UIFont systemFontOfSize:14];
        [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [self setBackgroundImage:[UIImage imageNamed:@"mainCellBackground"] forState:UIControlStateNormal];
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.imageView.width = self.width * 0.5;
    self.imageView.height = self.imageView.width;
    self.imageView.y = self.height * 0.1;
    self.imageView.centerX = self.width * 0.5;

    self.titleLabel.width = self.width;
    self.titleLabel.y = CGRectGetMaxY(self.imageView.frame);
    self.titleLabel.x = 0;
    self.titleLabel.height = self.height - self.titleLabel.y;
}
  • 一个控件不能响应点击事件,原因可能有:
    • 1> userInteractionEnabled = NO;
    • 2> enabled = NO;
    • 3> 父控件的userInteractionEnabled = NO;
    • 4> 父控件的enabled = NO;
    • 5> 控件已经超出父控件的边框范围

项目中由于没有设置父控件高度,所以点击没反应。

三 父控件footer加高度

  • 计算父控件高度方法1:根据有多少列,计算高度
    • 如果行数能被子控件数量整除,列数 = 总数 / 行数;
    • 如果行数不能被子控件数量整除,列数 = 总数 / 行数 + 1;
  // 设置footer的高度
    NSUInteger rowsCount = count / colsCount;
    if (count % colsCount) { // 不能整除,行数+1
        rowsCount++;
    }

合成公式写法如下:总页数 == (总个数 + 每页的个数 - 1) / 每页的个数

   NSUInteger rowsCount = (count + colsCount - 1) / colsCount;
   self.height = rowsCount * buttonH;
  • 方法2:拿到按钮的最高高度
self.height = CGRectGetMaxY(button.frame);

注意点:设置FooterView与设置height前后顺序不一样,效果不一样,期望是先设置height,在设置footerView

  • 解决方法1:重新设置footerView
    // 重新设置footerView
    UITableView *tableView = (UITableView *)self.superview;
    tableView.tableFooterView = self;
  • 解决方法2:直接改contentSize
   UITableView *tableView = (UITableView *)self.superview;
   tableView.contentSize = CGSizeMake(0, CGRectGetMaxY(self.frame));
  • button间加分割线
    • 方法1: 添加很多高宽为1的view
    • 方法2: 设置按钮宽度/高度减1,位置不变
    • 方法3: 美工提供一个带边框的图片
 [self setBackgroundImage:[UIImage imageNamed:@"mainCellBackground"] forState:UIControlStateNormal];

四 点击按钮push

  • 哪个按钮被点击
    • 加1数组计算按钮位置
      // 计算被点击按钮在子控件数组的位置
      NSUInteger index = [self.subviews indexOfObject:button];
      XMGSquare *square = self.squares[index];
    • 绑定tag
XMGSquare *square = squares[i];
button.tag = i;
XMGSquare *square = self.squares[button.tag];
  • 替换上述方法:封装button,一个button对应一个模型
- (void)setSquare:(XMGSquare *)square
{
    _square = square;

    // 数据
    [self setTitle:square.name forState:UIControlStateNormal];
    // 设置按钮的image
    [self sd_setImageWithURL:[NSURL URLWithString:square.icon] forState:UIControlStateNormal];
}
  • 点击按钮跳转webView
    • 判断按钮点击url地址以“http”开头
- (void)buttonClick:(XMGSquareButton *)button
{
    if ([button.square.url hasPrefix:@"http"]) {
        XMGWebViewController *webVc = [[XMGWebViewController alloc] init];

        // 取出当前选中的导航控制器
        UITabBarController *rootVc = (UITabBarController *)self.window.rootViewController;
        UINavigationController *nav = (UINavigationController *)rootVc.selectedViewController;
        [nav pushViewController:webVc animated:YES];
  //  不关心控制器的位置,位置会变化      
    //   [UIApplication sharedApplication].keyWindow;
    //   [[rootVc.childViewControllers lastObject] pushViewController:webVc animated:YES];
//        XMGLog(@"%@", rootVc.selectedViewController);
    }
}

五 网页显示

  • 遵守UIWebView代理
@interface WebViewController () <UIWebViewDelegate> 
@end
- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = self.square.name;
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.square.url]]];

    self.webView.backgroundColor = XMGCommonBgColor;
    // 设置偏移量
    self.webView.scrollView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
}
  • 前进后退箭头交互可否点击
#pragma mark - <UIWebViewDelegate>
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.backItem.enabled = webView.canGoBack;
    self.forwardItem.enabled = webView.canGoForward;
}

六 清除缓存

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationItem.title = @"设置";
    self.view.backgroundColor = XMGCommonBgColor;

    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:XMGSettingCellId];
    // 设置内边距(-25代表:所有内容往上移动25)
    self.tableView.contentInset = UIEdgeInsetsMake(XMGCommonMargin - 35, 0, 0, 0);

    XMGLog(@"%f", @"/Users/yonghuming/Desktop/课堂共享/顶部的cell.mp4".fileSize / 1000.0 / 1000.0);
// 手机上的磁盘缓存 == 从网络上下载的数据 + 写入的数据
// 手机上的磁盘缓存的数据类型 == 图片 + 多媒体文件
}
  • 获取文件夹的大小,文件夹没有直接获取大小的方法

    • 方法1:遍历文件夹下所有内容,计算相加

      // 总大小
      NSInteger size = 0;
      
      // 文件路径
      NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
      NSString *file = [caches stringByAppendingPathComponent:@"default"];
      
      // 文件管理者
      NSFileManager *mgr = [NSFileManager defaultManager];
      
      // 获得文件夹中的所有内容
      //    NSArray *contents = [mgr contentsOfDirectoryAtPath:file error:nil];
      NSArray *subpaths = [mgr subpathsAtPath:file];
      for (NSString *subpath in subpaths) {
          // 获得全路径
          NSString *fullSubpath = [file stringByAppendingPathComponent:subpath];
          // 获得文件属性
          NSDictionary *attrs = [mgr attributesOfItemAtPath:fullSubpath error:nil];
      //     size += [attrs[NSFileSize] integerValue];
          size += attrs.fileSize;
      }
      XMGLog(@"%@ %f", file, size / 1000.0 / 1000.0);
    • 方法2:引用遍历器/迭代器

  // 总大小
  NSInteger size = 0;

    // 文件路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    NSString *file = [caches stringByAppendingPathComponent:@"default"];

   // 文件管理者
   NSFileManager *mgr = [NSFileManager defaultManager];

   // 获得文件夹中的所有内容
   NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath:file];
    for (NSString *subpath in enumerator) {
       // 获得全路径
       NSString *fullSubpath = [file stringByAppendingPathComponent:subpath];
       // 获得文件属性
       NSDictionary *attrs = [mgr attributesOfItemAtPath:fullSubpath error:nil];
   //   size += [attrs[NSFileSize] integerValue];
        size += attrs.fileSize;
    }
    XMGLog(@"%@ %f", file, size / 1000.0 / 1000.0);
  • 计算大小功能抽取分类,字符串做分类(方便)
    • 适用计算文件夹大小,如果是文件,没法输出大小,需要加判断
- (NSInteger)fileSize
{
    // 文件管理者
    NSFileManager *mgr = [NSFileManager defaultManager];
    // 是否为文件夹
    BOOL isDirectory = NO;
    // 这个路径是否存在
    BOOL exists = [mgr fileExistsAtPath:self isDirectory:&isDirectory];
    // 路径不存在
    if (exists == NO) return 0;

    if (isDirectory) { // 文件夹
        // 总大小
        NSInteger size = 0;
        // 获得文件夹中的所有内容
        NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath:self];
        for (NSString *subpath in enumerator) {
            // 获得全路径
            NSString *fullSubpath = [self stringByAppendingPathComponent:subpath];
            // 获得文件属性
            size += [mgr attributesOfItemAtPath:fullSubpath error:nil].fileSize;
        }
        return size;
    } else { // 文件
        return [mgr attributesOfItemAtPath:self error:nil].fileSize;
    }
}
  • 封装一个清除缓存的操作,自定义cell
/** 缓存路径 */
#define XMGCacheFile [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"default"]

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        self.textLabel.text = XMGDefaultText;

        // 禁止点击事件
        self.userInteractionEnabled = NO;

        // 右边显示圈圈
        UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        [loadingView startAnimating];
        self.accessoryView = loadingView;

        // 计算大小
        [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
            // 计算缓存大小
            NSInteger size = XMGCacheFile.fileSize;
            CGFloat unit = 1000.0;
            NSString *sizeText = nil;
            // 文件大小显示格式
            if (size >= unit * unit * unit) { // >= 1GB
                sizeText = [NSString stringWithFormat:@"%.1fGB", size / unit / unit / unit];
            } else if (size >= unit * unit) { // >= 1MB
                sizeText = [NSString stringWithFormat:@"%.1fMB", size / unit / unit];
            } else if (size >= unit) { // >= 1KB
                sizeText = [NSString stringWithFormat:@"%.1fKB", size / unit];
            } else { // >= 0B
                sizeText = [NSString stringWithFormat:@"%zdB", size];
            }
            NSString *text = [NSString stringWithFormat:@"%@(%@)", XMGDefaultText, sizeText];

            // 回到主线程
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                self.textLabel.text = text;
                self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                self.accessoryView = nil; // 圈圈消失
                // 允许点击事件
                self.userInteractionEnabled = YES;
            }];
        }];
    }
    return self;
}
  • 取消cell选中时背景颜色
#pragma mark - <代理>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 取消选中
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    // 清除缓存
    XMGClearCacheCell *cell = (XMGClearCacheCell *)[tableView cellForRowAtIndexPath:indexPath];
    [cell clearCache];
}
  • 模拟清除缓存操作
- (void)clearCache
{
    [SVProgressHUD showWithStatus:@"正在清除缓存" maskType:SVProgressHUDMaskTypeBlack];

    [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
        [[NSFileManager defaultManager] removeItemAtPath:XMGCacheFile error:nil];

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [SVProgressHUD showSuccessWithStatus:@"清除成功"];

            self.textLabel.text = XMGDefaultText;

            // 禁止点击事件
            self.userInteractionEnabled = NO;
        }];
    }];
}

七 不同标识cell的共存

  • 当有多个样式不一样的cell时,不方便cell循环利用,可以通过注册2或多个cell(cellID)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0 && indexPath.row == 0) { // 清除缓存的cell
        XMGClearCacheCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGClearCacheCellId];
 //    [cell updateStatus];
        return cell;
    } else if (indexPath.section == 1 && indexPath.row == 2) {
        return [tableView dequeueReusableCellWithIdentifier:XMGThirdCellId];
    } else {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGOtherCellId];
        cell.textLabel.text = [NSString stringWithFormat:@"%zd - %zd", indexPath.section, indexPath.row];
        return cell;
    }
}
  • 一旦离开缓存池,cell一些动画会自动停掉,想要不停动画,更新状态
- (void)updateStatus
{
    if (self.accessoryView == nil) return;

    // 让圈圈继续旋转
    UIActivityIndicatorView *loadingView = (UIActivityIndicatorView *)self.accessoryView;
    [loadingView startAnimating];
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值