objective-c一个简单的异步下载的封装

本文介绍了如何使用Objective-C进行异步数据下载的封装,包括关键代码示例和注意事项,强调了异步下载的特点及数据处理时机,提醒开发者在处理下载数据时要确保在完成回调中进行以避免空数据错误。
摘要由CSDN通过智能技术生成

话不多说,直接开始代码,代码中有比较详尽的注释。

首先是对方法的封装类

ZXRequest.h

#import <Foundation/Foundation.h>

@interface ZXRequest : NSObject<NSURLConnectionDataDelegate>
{
    //用来接收返回的数据
    NSMutableData * _myData;
}
//先写做网络请求需要的属性

@property(nonatomic,copy)NSString * url;

//是否缓存
@property(nonatomic,assign)BOOL isCashe;

//网络请求之后调用的block
@property(nonatomic,copy)void(^finishBlock)(NSData *data);

//网络请求失败后调用的block
@property(nonatomic,copy)void(^faildBlock)();

//开始网络请求
-(void)startRequest;




@end

ZXRequest.m

#import "ZXRequest.h"
//MD5加密方式
#import "NSString+Hashing.h"

@implementation ZXRequest

//初始化方法
-(id)init{
    if (self = [super init]) {
        //在初始化方法里 初始化data
        _myData = [[NSMutableData alloc] init];
        
    }
    return self;
}

//执行.h方法
-(void)startRequest{
    //先判断是否用缓存 ,缓存里有没有数据
    if (self.isCashe) {
        //先把缓存的路径找到
        NSString * path = [NSHomeDirectory() stringByAppendingFormat:@"tmp/%@",[self.url MD5Hash]];
        //在判断当前路径下是否有文件
        NSFileManager * maneger = [NSFileManager defaultManager];
        //如果文件存在于path目录下
        if ([maneger fileExistsAtPath:path])
        {
            //用path生成一个data对象 然后返回给finishBlock 然后return
            NSData * data = [NSData dataWithContentsOfFile:path];
            self.finishBlock(data);
            return;
        }
        
        //如果没有使用缓存 或者缓存中没有数据,进行网络请求

    }
        NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString: self.url]];
        [NSURLConnection connectionWithRequest:request delegate:self];
    
}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    
    //收到请求后做出的响应
    //这里做的是打开系统的Activity控件(网络数据请求时屏幕左上角旋转的加载动画)
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    //NSURLConnection下载的数据就是这个方法中的data,不过这些数据是零散的,我们需要将这些数据拼接到我们定义的_myData中备用
    [_myData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    //先判断是否需要做缓存,
    //若需要缓存的话,把所有返回的数据存到沙盒目录下
    if (self.isCashe) {
        //先找到缓存路径
        NSString * path = [NSHomeDirectory() stringByAppendingFormat:@"tmp/%@",[self.url MD5Hash]];
        [_myData writeToFile:path atomically:YES];
    }
    //还要把所有的_myData传给用到数据的类里面
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    //调用代理方法(一般是处理数据)
    self.finishBlock(_myData);
    
}
@end
通过一个管理类来使用上述的类。

只需要一个+方法即可

ZXRequestManager.h

#import <Foundation/Foundation.h>
#import "ZXRequest.h"
@interface ZXRequestManager : NSObject

+(void)requestWithURL:(NSString *)url IsCashe:(BOOL)isCache finish:(void(^)(NSData *data))finishBlock failed:(void(^)())failedBlock;


@end
ZXRequestManager.m

#import "ZXRequestManager.h"
#import "ZXRequest.h"
@implementation ZXRequestManager

+(void)requestWithURL:(NSString *)url IsCashe:(BOOL)isCache finish:(void (^)(NSData *))finishBlock failed:(void (^)())failedBlock{
    //创建ZXRequst对象
    ZXRequest * request = [[ZXRequest alloc] init];
    request.url = url;
    request.isCashe = isCache;
    request.finishBlock = finishBlock;
    request.faildBlock = failedBlock;
    [request startRequest];
}

@end
在管理类的方法中,完成对工具类的各项属性赋值,然后在所需的地方进行调用即可。

在需要下载数据的类中写下述代码

    [ZXRequestManager requestWithURL:@"网址" IsCashe:YES finish:^(NSData *data) {
        
        NSDictionary *dic =  [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
        NSArray * array = [dic objectForKey:@"list"];
        for (NSDictionary * d in array) {
            NSLog(@"%@",[d objectForKey:@"name"]);
        }
        
    } failed:^{
        
        NSLog(@"没网滚粗");
    }];
在调用时要传入的参数有  网址   是否缓存(YES or NO)

另外,还需要写两个block方法

finish:^(NSData *data){}其中写的是下载完成后对数据的处理,这里是对数据进行遍历输出

failed:^{ }其中写的是在下载失败时进行的操作。


需要注意的是,由于在这种方法下,数据是"异步下载",并不是在执行了这个方法之后就会完成了数据的下载,在此期间,如果在代码的其他地方需要用到下载来的数据,必须要将对应的处理下载finish:^(NSData *data){}的方法体中,否则会出现错误(一般是数据为空的错误)。



最后,由于在数据存储的时候采用了加密,所以需要导入一个数据加密的类。

这里提供方法的实现(转)

NSString+Hashing.h


#import <Foundation/Foundation.h>


@interface NSString (NSString_Hashing)

- (NSString *)MD5Hash;

+(NSString*)fileMD5:(NSString*)path;

+(NSString*)dataMD5:(NSData*)data;
@end

NSString+Hashing.m


#import "NSString+Hashing.h"
#import <CommonCrypto/CommonDigest.h>

@implementation NSString (NSString_Hashing)

- (NSString *)MD5Hash
{
	const char *cStr = [self UTF8String];
	unsigned char result[16];
	CC_MD5(cStr, strlen(cStr), result);
	return [NSString stringWithFormat:
			@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
			result[0], result[1], result[2], result[3], 
			result[4], result[5], result[6], result[7],
			result[8], result[9], result[10], result[11],
			result[12], result[13], result[14], result[15]];
}
+(NSString*)dataMD5:(NSData*)data
{
    CC_MD5_CTX md5;  
    
    CC_MD5_Init(&md5);  
    
    CC_MD5_Update(&md5, [data bytes], [data length]); 
    
    unsigned char digest[CC_MD5_DIGEST_LENGTH];  
    CC_MD5_Final(digest, &md5);  
    NSString* s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",  
                   digest[0], digest[1],   
                   digest[2], digest[3],  
                   digest[4], digest[5],  
                   digest[6], digest[7],  
                   digest[8], digest[9],  
                   digest[10], digest[11],  
                   digest[12], digest[13],  
                   digest[14], digest[15]];  
    return s;  
}
+(NSString*)fileMD5:(NSString*)path  
{  
    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];  
    if( handle== nil ) return @"ERROR GETTING FILE MD5"; // file didnt exist  
    
    CC_MD5_CTX md5;  
    
    CC_MD5_Init(&md5);  
    
    BOOL done = NO;  
    while(!done)  
    {  
        NSData* fileData = [handle readDataOfLength: 10240];  
        CC_MD5_Update(&md5, [fileData bytes], [fileData length]);  
        if( [fileData length] == 0 ) done = YES;  
    }  
    unsigned char digest[CC_MD5_DIGEST_LENGTH];  
    CC_MD5_Final(digest, &md5);  
    NSString* s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",  
                   digest[0], digest[1],   
                   digest[2], digest[3],  
                   digest[4], digest[5],  
                   digest[6], digest[7],  
                   digest[8], digest[9],  
                   digest[10], digest[11],  
                   digest[12], digest[13],  
                   digest[14], digest[15]];  
    return s;  
}  

@end





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值