iOS开发之异步加载网络图片并缓存本地实现瀑布流(二)

在上一篇博客中,我们实现了异步加载图片的功能,由于上次的时间问题,讲的比较简单所以在这篇文章中,我对前面代码中涉及到得关键代码再做一次详细的解释。

先看一个函数,

 

/*
 * @brief 图片加载通用函数
 * @parma imageName 图片名
 */
- (void)imageStartLoading:(NSString *)imageName{
    NSURL *url = [NSURL URLWithString:imageName];
    if([_fileUtil hasCachedImage:url]){
        UIImageView *imageView = [[UIImageView alloc] init];
        NSString *path = [_fileUtil pathForUrl:url];
        imageView = [_imageLoad compressImage:MY_WIDTH/3 imageView:nil imageName:path flag:NO];
        [self addImage:imageView name:path];
        [self adjustContentSize:NO];
    }else{
        UIImageView *imageView = [[UIImageView alloc] init];
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:url, @"URL",
                             imageView, @"imageView", nil];
        [NSThread detachNewThreadSelector:@selector(cacheImage:) toTarget:[ImageCacher shareInstance] withObject:dic];
    }
}


这个函数的作用是为每一张网络图片开启一个下载线程,但是因为该程序用到了图片缓存的技术,所以在每次开线程下载图片的时候都会去本地缓存目录查找一下,

 

该图片是否已经存在,如果存在则直接加载在视图中。一般OC的线程函数有三个,NSThread, Cocoa Operations,和GCD,(想要了解三者的异同点可查看:点击打开链接),

这里我用了比较轻量级的NSThread,detachNewThreadSelector函数中所传的函数名: cacheImage是类ImageCache中得函数,这里通过iOS开发中使用的比较多的单例模式,

得到了ImageCache的句柄,参数dic中主要存放了图片的网络地址以及imageView用来add图片进视图以及根据图片的大小压缩成合适的大小.

 

接下来是cacheImage函数:

 

- (void)cacheImage:(NSDictionary*)dic{
    NSURL *url = [dic objectForKey:@"URL"];
    NSFileManager *fileManage = [NSFileManager defaultManager];
    NSData *data = [NSData dataWithContentsOfURL:url];
    
    NSString *fileName = [_fileUtil pathForUrl:url];
    if(data){
        [fileManage createFileAtPath:fileName contents:data attributes:nil];
    }
    
    UIImageView *imageView = [dic objectForKey:@"imageView"];
    imageView.image = [UIImage imageWithData:data];
    imageView = [_imageLoader compressImage:MY_WIDTH/3 imageView:imageView imageName:nil flag:YES];
    [self.myDelegate addImage:imageView name:fileName];
    [self.myDelegate adjustContentSize:NO];
}


该函数用来将下载下来的图片缓存进入文件沙盒中(缓存文件可以自己定义并指定),并且按照图片的大小进行等比例压缩,固定宽度是屏幕的三分之一大小,这样一来,

 

图片显示就不会出现不全或失真的现象。由于ImageCache和MyScrollView是两个独立的类,所以这里通过使用ios的delegate(代理)来进行图片在scrollView上的加载,

(什么是代理模式:点击打开链接).

 

下面我们来看如何在沙盒中建立缓存文件夹,其实缓存文件夹跟普通的文件夹一样,只是该文件夹是专门用来存放缓存文件的而已。类代码如下所示:

 

//
//  FileUtil.m
//  Test515
//
//  Created by silicon on 14-5-30.
//  Copyright (c) 2014年 silicon. All rights reserved.
//

#import "FileUtil.h"

@implementation FileUtil

+ (FileUtil *)shareInstance{
    static FileUtil *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    
    return instance;
}

/*
 @breif 创建缓存文件夹
 */
- (void)createPathInDocumentDirectory{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *diskCachePath = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageCache"] retain];
    NSLog(@"%@", diskCachePath);
    
    if(![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath]){
        NSError *error = nil;
        [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath
                                  withIntermediateDirectories:YES
                                                   attributes:nil
                                                        error:&error];
    }
}

/*
 @breif     获取沙盒中文档目录
 @param     fileName:文件名字
 */
- (NSString *)pathInDocumentDirectory:(NSString *)fileName{
    NSArray *fileArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
                                                             NSUserDomainMask, YES);
    NSString *cacheDirectory = [fileArray objectAtIndex:0];
    return [cacheDirectory stringByAppendingPathComponent:fileName];
}

/*
 @breif     获取沙盒中缓存文件目录
 @param     fileName:文件名字
 */
- (NSString *)pathInCacheDirectory:(NSString *)fileName{
    NSArray *fileArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
                                                             NSUserDomainMask, YES);
    NSString *cacheDirectory = [fileArray objectAtIndex:0];
    return [cacheDirectory stringByAppendingPathComponent:fileName];
}

/*
 @breif     判断是否已经缓存
 @param     url:图片名称
 */
- (BOOL)hasCachedImage:(NSURL *)url{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if([fileManager fileExistsAtPath:[self pathForUrl:url]]){
        return YES;
    }else{
        return NO;
    }
}

/*
 @breif     根据URL的給图片命名
 @param     url:图片url
 */
- (NSString *)pathForUrl:(NSURL *)url{
    return [self pathInCacheDirectory:[NSString stringWithFormat:@"qiaoqiao-%u", [[url description] hash]]];
}

@end


在这次的demo中,我新加入了用户可以点击图片放大 并可以左右滑动的功能,其实实现起来很简单,我一开始为每一个ScrollView 中得ImageView都设置了tag值,并且添加了

 

手势(UITapGestureRecognizer),当用户点击图片时,程序可以根据点击视图的tag值来获得相应的图片是哪一张,从而可以加载。支持左右滑动的功能在新的界面中增加了

一个ScrollView,然后将下载下来的图片添加到scrollView中。代码如下

 

//
//  PhotoViewController.m
//  Test515
//
//  Created by silicon on 14-5-22.
//  Copyright (c) 2014年 silicon. All rights reserved.
//

#import "PhotoViewController.h"
#import "ImageLoader.h"

@interface PhotoViewController ()

@end

@implementation PhotoViewController
@synthesize scrollView = _scrollView;
@synthesize imageArray = _imageArray;
@synthesize page = _page;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    [self.view setFrame:CGRectMake(0, 0, MY_WIDTH, MY_HEIGHT)];
    [self.view setBackgroundColor:[UIColor blackColor]];
    
    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, MY_WIDTH, MY_HEIGHT)];
    _scrollView.delegate = self;
    _scrollView.contentSize = CGSizeMake(MY_WIDTH * [_imageArray count], MY_HEIGHT);
    _scrollView.showsVerticalScrollIndicator = NO;
    _scrollView.showsHorizontalScrollIndicator = NO;
    _scrollView.backgroundColor = [UIColor blackColor];
    _scrollView.bounces = YES;
    _scrollView.pagingEnabled = YES;
    [self.view addSubview:_scrollView];
    
    //图片添加事件响应
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closePhotoView)];
    tapRecognizer.delegate = self;
    _scrollView.userInteractionEnabled = YES;
    [_scrollView addGestureRecognizer:tapRecognizer];
    [tapRecognizer release];
    
    [self loadingImages];
}

- (void)viewWillAppear:(BOOL)animated{
    [_scrollView setContentOffset:CGPointMake([_imageArray indexOfObject:_imageName] * MY_WIDTH, 0)];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//关闭
- (void)closePhotoView{
    [self.view removeFromSuperview];
}

- (void)dealloc{
    [_scrollView release];
    [super dealloc];
}

- (void)loadingImages{
    //加载图片
    for(int i = 0; i < [_imageArray count]; i++){
        NSString *picName = [_imageArray objectAtIndex:i];
        UIImageView *imageV = [[ImageLoader shareInstance] compressImage:MY_WIDTH imageView:nil imageName:picName flag:NO];
        
        float width = imageV.image.size.width;
        float height = imageV.image.size.height;
        
        float new_width = MY_WIDTH;
        float new_height = (MY_WIDTH * height)/width;
        
        imageV.frame = CGRectMake(MY_WIDTH * i, 0, new_width, new_height);
        [_scrollView addSubview:imageV];
        [imageV release];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)_scrollView{

}

@end


基本上这个程序的主要功能就这些啦,其他的一些有关瀑布流的实现请看我前面的博客吧!点击打开链接

 

如果有哪里写的或说的有问题,欢迎各位大神指出来。

 

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HelloWord杰少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值