IOS学习 NSOperation cell存储图片思路 沙盒路径查找 数组中添加空对象 block循环引用风险

沙盒路径查找方法:

1.在程序中打一个断点,运行

2.在打印窗口输入:po NSHomeDirectory() 回车

3.拷贝路径,在文件夹下,按菜单栏->前往->前往文件夹 





#import "HomeTableViewController.h"

#import "CZApp.h"

@interface HomeTableViewController ()

//plist文件数据的容器

@property(nonatomic,strong)NSArray *listArray;


//管理全局下载操作的队列

@property(nonatomic,strong)NSOperationQueue *opQueue;


//所有下载操作的缓存池

@property(nonatomic,strong)NSMutableDictionary *operationCache;


//所有图像的缓存

@property(nonatomic,strong)NSMutableDictionary *imageCache;


@end


@implementation HomeTableViewController


//懒加载

-(NSArray *)listArray{

    if (_listArray == nil) {

        NSString *path = [[NSBundle mainBundle]pathForResource:@"videos.plist" ofType:nil];

        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];

        

        //字典转模型

        NSMutableArray *muArray = [[NSMutableArray alloc]init];

        for (NSDictionary *dict in dictArray) {

            CZApp *app = [CZApp appWithDict:dict];

            [muArray addObject:app];

        }

        _listArray = muArray;

    }

    return _listArray;

}


-(NSMutableDictionary *)operationCache{

    if (_operationCache == nil) {

        _operationCache = [NSMutableDictionary dictionary];

    }

    return _operationCache;

}


-(NSMutableDictionary *)imageCache{

    if (_imageCache == nil) {

        _imageCache = [[NSMutableDictionary alloc]init];

    }

    return _imageCache;

}


-(NSOperationQueue *)opQueue{

    if (_opQueue == nil) {

        _opQueue = [[NSOperationQueue alloc]init];

    }

    return _opQueue;

}


#pragma mark - Table view data source


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.listArray.count;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    HomeTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"cell"];

    if (cell==nil) {

        cell=[[HomeTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];

        cell.selectionStyle=UITableViewCellSelectionStyleNone;

    }

    

    CZApp *app = self.listArray[indexPath.row];

    cell.label.text = app.video_title;

    cell.detailLabel.text = app.video_subTitle;

    

    //判断图片缓存池中是否有图片

    if ([self.imageCache objectForKey:app.video_img]) {

        NSLog(@"不用上网下载图片,从图片缓存池中取");

        //显示图片到cell

        cell.imageView.image = self.imageCache[app.video_img];

        return cell;

    }

    

    //判断沙盒里有没有图片

    UIImage *image = [UIImage imageWithContentsOfFile:[self cachePathWithURL:app.video_img]];

    

    if (image) {

        NSLog(@"从沙盒里加载图片-----");

        //1.设置图片缓存到内存

        [self.imageCache setObject:image forKey:app.video_img];

        

        //2.显示图片到cell

        cell.imageView.image = self.imageCache[app.video_img];

        return cell;

    }

    

    //显示占位图片

    cell.dimageView.image = [UIImage imageNamed:@"user_default"];

    

    //下载图片(重构剪出去)

    [self downloadimage:indexPath];

    

    return cell;

}


-(void)downloadimage:(NSIndexPath *)indexPath{

    CZApp *app = self.listArray[indexPath.row];

    

    //判断操作缓存池中是否存在下载图片的操作

    if (self.operationCache[app.video_img]) {

        NSLog(@"从缓存池中玩命下载......");

        return;

    }

    

    /*block 会有循环引用的风险 -------对外部变量的强引用

     --self 要小心

     --可以借助dealloc方法,判断是否循环引用

    */

    //多线程异步

    NSBlockOperation *downloadop = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"图片下载中......");

        //1.下载图片

        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.video_img]];

        UIImage *image = [UIImage imageWithData:data];

        

        //2.将下载的图片放在imageCache缓存中

        /*字典的赋值,不能为nil

         *[NSNull null]:空对象,可以放入字典和数组中

         * NULLC语言里的空指针

         * nilOC语言中指向空对象的指针

         * Nil:空类,一般用不到

         * NSArray *arr = [NSArray arrayWithObjects:@"1", [NSNull null],@"2",nil,@"3"];

         * NSLog(@"%@",arr);  //数组中只有3个对象,nil后面的没用         */

       

        if (image) {

            [self.imageCache setObject:image forKey:app.video_img];

            

            //将图片存入沙盒

            [data writeToFile:[self cachePathWithURL:app.video_img] atomically:YES];

            

            //将操作从缓存池中移除

            [self.operationCache removeObjectForKey:app.video_img];

        }

    

        //3.更新UI

        [[NSOperationQueue mainQueue]addOperationWithBlock:^{

            //刷新当前Cell

            [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

        }];

    }];

    

    //将操作放到队列里

    [self.opQueue addOperation:downloadop];

    NSLog(@"操作的数量--------%lu",self.opQueue.operationCount);

    

    //将操作添加到缓存池中(使用图片的URL作为Key

    [self.operationCache setObject:downloadop forKey:app.video_img];

}


//拼接一个文件在沙盒里的全路径

-(NSString *)cachePathWithURL:(NSString *)urlstr{

    //1.获取缓存的路径

    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];

    

    //2.把路径和url拼接起来

    //http://c.hiphotos.baidu.com/video/pic/item/ae51f3deb48f8c545bc3315739292df5e0fe7fb2.jpg

    return [cachePath stringByAppendingPathComponent:urlstr.lastPathComponent];

}


//测试沙盒路径是否拼接正确

- (void)viewDidLoad {

    [super viewDidLoad];

    NSLog(@"path %@",[self cachePathWithURL:@"http://c.hiphotos.baidu.com/video/pic/item/ae51f3deb48f8c545bc3315739292df5e0fe7fb2.jpg"]);

}


-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    return 110;

}



- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    

    //内存警告时,需要在这里进行一些内存清理工作,如果不处理,会被系统强制闪退

    //清理图片的缓存

    [self.imageCache removeAllObjects];

    

    //清理操作的缓存

    [self.operationCache removeAllObjects];

    

    //取消下载队列里的任务

    [self.opQueue cancelAllOperations];

}


-(void)dealloc{

    //根控制器不会消除

    NSLog(@"8888------");

}


@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值