# DataBoss **Repository Path**: juwenz/DataBoss ## Basic Information - **Project Name**: DataBoss - **Description**: No description available - **Primary Language**: Objective-C - **License**: MIT - **Default Branch**: master - **Homepage**: http://my.oschina.net/juwenz/blog/389295 - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2015-02-13 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #DataBoss `DataBoss`是基于`ASIHTTPRequset`的二次封装,目的是用更少的代码完成更多的功能,简约是美。 ##功能简介 `DataBoss`是由实际项目发展而来,最初是为了解决项目中的种种需求而设计,所以功能本身是具有局限性,不能满足所有的需求,因此希望更多的人参与进来不断完善它!它的功能主要分为两类:一是数据请求工具,二是UITableView工具,具体如下: - 数据请求工具 - 数据请求(包括POST和GET方式) - 请求并缓存图片 - 上传数据(POST方式) - UITableView工具 - 列表信息请求 - 分页查询 - 刷新 数据请求部分主要用的是`block`方式实现,在`block`中实现自己的业务代码;`UITableView`工具主要用代理(deletage)实现。它们都需要请求队列(`ASINetworkQueue`)并作为参数手动传入方法,这样就可以在请求的过程随时打断请求,以免在某些情况下造成程序的Crash。 ##方法(API)介绍 ###数据请求工具 - 请求数据 /** * 发起异步请求,回调函数中返回NSDictionary * * @param url 请求链接 * @param queue 管理请求的队列,详情查看 |ASINetworkQueue| * @param handler 异步请求的回调 */ + (void) sendAsynchronousRequest:(NSString *)url queue:(ASINetworkQueue*)queue completionHandler:(void (^)(ASIHTTPRequest *request, NSDictionary *json, NSString *errorMsg))handler; 如果请求中出现错误,会返回给`errorMsg`,错误包含网络无连接和非200状态的请求结果,此处不涉及到断点续传等情况,所以没有考虑20x状态。默认的缓存策略是`ASIAskServerIfModifiedWhenStaleCachePolicy`,如果需要指定缓存策略可以用下面这个方法。 /** * 发起异步请求,回调函数中返回NSData * * @param url 请求链接 * @param cachePolicy 缓存策略,查看 |ASICachePolicy| * @param queue 管理请求的队列,详情查看 |ASINetworkQueue| * @param handler 异步请求的回调 */ + (void)sendAsynchronousRequest:(NSString *)url cachePolicy:(ASICachePolicy)cachePolicy queue:(ASINetworkQueue *)queue completionHandlerWithData:(void (^)(ASIHTTPRequest *request, NSData *data, NSString *errorMsg))handler; /** * 发起异步请求,回调函数中返回NSDictionary * * @param url 请求链接 * @param cachePolicy 缓存策略,查看 |ASICachePolicy| * @param queue 管理请求的队列,详情查看 |ASINetworkQueue| * @param handler 异步请求的回调 */ + (void)sendAsynchronousRequest:(NSString *)url cachePolicy:(ASICachePolicy)cachePolicy queue:(ASINetworkQueue *)queue completionHandlerWithDictionary:(void (^)(ASIHTTPRequest *requset, NSDictionary *json, NSString *errorMsg))handler; 以上两个方法可以指定缓存策略,唯一不同点是返回的结果数据类型不一样,一个是把返回结果序列化成了`NSDictionary`类型,另一个是`NSData`类型,根据自己的需求选择合适的方法。 - 图片(文件)请求 /** * 请求并且缓存图片,回调函数返回UIImage对象 * * @param picturePath 图片路径 * @param _queue 请求队列,记得在dealloc的时候取消queue里面的请求 * @param handler 回调函数 */ + (void)requsetAndCacheImage:(NSString *)picturePath queue:(ASINetworkQueue *)queue completion:(void(^)(ASIHTTPRequest *request , UIImage *image , NSString *errorMsg))handler; 传入图片的网络路径(`picturePath`),返回`UIImage`对象。有人会问,如果要请求其它文件该如何办,`DataBoss`提供一个更通用的方法来请求和缓存文件: /** * 请求并且缓存文件,返回缓存路径,通过缓存路径取得文件 * * @param fileURL 文件路径 * @param queue 请求队列 * @param handler 回调函数 */ + (void)requestAndCacheFile:(NSString *)fileURL queue:(ASINetworkQueue *)queue completion:(void(^)(ASIHTTPRequest *request, NSString* cachedPath, NSString* errorMsg))handler; 同上面一样,传入文件请求路径,返回的是本地的缓存路径,可以通过路径取得文件,之后对文件进行何种操作都可以。 对于图片请求,还会有延时请求的需求,即先把所有的图片请求加入队列但此时不请求,等一声令下,才开始请求,当然不是全部都请求,根据`queue`配置同时最大请求数量而定,方法如下: /** * 延时请求并且缓存,回调函数返回UIImage,调用[queue go]开始请求图片 * * @param picturePath 图片路径 * @param queue 请求队列,记得在dealloc的时候取消queue里面的请求 * @param handler 回调函数 */ + (void)requsetAndCacheImageLazy:(NSString *)picturePath queue:(ASINetworkQueue *)queue completion:(void(^)(ASIHTTPRequest *request , UIImage *image , NSString *errorMsg))handler; - 上传文件 此部分参数略微复杂(第一印象),不过理解参数之后就会很清晰了,先看方法: /** * 上传文件到服务器,可以携带其他参数 * * @param data 文件的NSData * @param server 上传链接 * @param key 服务器接受文件的key * @param type 文件类型,kDataBossFileTypeJPEG,kDataBossFileTypePNG,kDataBossFileTypeMP4 * @param queue 上传队列 * @param params 其他参数 * @param handler 上传成功的回调block */ + (void)uploadFile:(NSData *)data toServer:(NSString *)server withKey:(NSString *)key contentType:(NSString *)type queue:(ASINetworkQueue *)queue andParams:(NSArray *)params complete:(void(^)(ASIFormDataRequest *request,NSDictionary *json,NSString *errorMsg))handler; 需要说明的是`params`参数,它是包含其他需要上传参数的集合,参数的形式是以键值对方式组织的,`params`可能是下面的值: NSArray *params = @[ @{@"key":@"username",@"value":@"guest"}, @{@"key":@"sex",@"value":@1} ]; 返回结果是已经序列话成的`NSDictionary`对象。这样分解一下,是不是感觉好多了,总结一下,参数包含文件,服务器接收文件的key,文件类型、其它的参数和服务器地址,如果文件类型不满足请自行添加,并在git`pull`给我。 主要功能就是这些,如果需要详细了解,可以结合代码理解。下面看看如何使用它们。 ###UITableView工具 数据请求工具部分上面已经介绍完了,接着介绍如何使用`DataBoss`配合`UITableView`使用,满足普遍需求。 此部分主要有以下几个方法: - (id)initWithAction:(NSString *)action; - (void)fetchObjectsInBackground; - (void)refresh; - (void)nextPage; - (void)cancel; 正如方法名表达的一样,`nextPage`是请求下一页数据,`refresh`刷新数据,即请求第一页数据,`fetchObjectsInBackground`异步请求数据,`cancle`取消请求。 下面通过假设场景来说明,假设有个`UITableView`需要展示酒店信息(`Hotel`对象),只需定义一个`HotelFetcher`继承自`DataBoss`,在`HotelFetcher.m`文件里面重写父类的`- assemble:data authorization:flag errorMsg:error`方法,此方法的返回值是一个数据,里面包含的是`Hotel`对象,可能的代码片段如下: - (NSArray *)assemble:(NSData *)data authorization:(BOOL *)flag error:(NSError *__autoreleasing *)error { NSMutableArray *datas = [[NSMutableArray alloc] init]; __autoreleasing NSError *err; NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&err]; if (err!=nil) { //JSON格式错误 error = &err; return nil; } //如果JSON对象不为空,并且没有错误信息 if(json != nil && err == nil){ //解析NSDictionary,组装成Hotel对象 //把Hotel对象加入datas中 }else{ __autoreleasing NSError *customError = [NSError errorWithDomain:@"com.yourcompany.projectname" code:1 userInfo:@{@"NSLocalizedDescription":[json objectForKey:@"result"]}];//result里面包含错误信息 error = &customError; } } } return datas; } 接下来初始化一个`HotelFetcher`对象`dataFetcher`,注意需要分页查询时要设置一下参数: [dataFetcher setAction:@""];//设置请求Action,不要包含limit和page,会自动设置 dataFetcher.limit = 10; //分页条数,默认10条 dataFetcher.timeout = 10; //请求超时秒数,默认10秒 dataFetcher.enablePaging = YES; //是否支持分页,默认NO dataFetcher.delegate = self; //请求回数据的代理 出异步请求后,接受数据的代理方法是 - (void)fetcher:(DataBoss *)fetcher fetchResult:(NSArray *)objects error:(NSString *)errorMsg authorization:(BOOL)authorization sMore:(BOOL)hasMore { if(errorMsg){ [self showTips:errorMsg];//显示错误信息 }else{ _hasMore = hasMore;//是否还有下一页, [datas addObjectsFromArray:objects]; [self.tableView reloadData]; } } 整个流程介绍完毕,总的来说需要做的有两件事情 - 第一,如何把请求回来的数据封装成想要的对象,比如系统里可能有`Model1`、`Model2`,这个请求的结果到底返回哪类对象的数组,需要自己去实现,也就是`- assemble:data authorization:flag errorMsg:error` - 第二,数据返回来(同一个代理方法返回的),需要做何种处理,具体业务逻辑需要自己判断,比如有可能是刷新,也有可能是下一页操作,即`- (void)fetcher:(DataBoss *)fetcher fetchResult:(NSArray *)objects error:(NSString *)errorMsg authorization:(BOOL)authorization hasMore:(BOOL)hasMore` 使用`DataBoss`后,不用写很多重复的请求代码就能很轻松的实现分页,请求等功能。 ##实战 初始化`ASINetworkQueue`对象是通用代码,在此单独写出来,以下案例中的`queue`不再一一初始化: ASINetworkQueue *queue= [[ASINetworkQueue alloc] init]; //可以配置其他属性,比如最大连接数等 #场景一 起一个检测更新的请求: NSString *url = @""; //检测地址 [DataBoss sendAsynchronousRequest:url cachePolicy:ASIAskServerIfModifiedCachePolicy queue:queue mpletionHandlerWithDictionary:^(ASIHTTPRequest *requset, NSDictionary *json, NSString *errorMsg) { if (!errorMsg) { //没有请求错误,解析json内容来判断是否有更新 //可以NSLog(@"%@",json);查看返回的内容 }else{ //请求出现错误,可以在errorMsg中查看 } }]; ###场景二:请求图片 NSString *urlStr = @"";//图片的地址 [DataBoss requsetAndCacheImage:urlStr queue:queue completion:^(ASIHTTPRequest *request, UIImage *image, NSString *errorMsg) { if (!errorMsg) { //没有问题,可以用image对象 }else{ //请求错误,处理错误 }]; 如果再次请求该图片,将使用缓存的图片。 ###场景三:上传文件 NSString *urlStr = @"";//接收数据的链接 NSArray *params = @[ @{@"key":@"key1",@"value":value1==nil?@"":value1}, @{@"key":@"key2",@"value":value2==nil?@"":value2} ]; [DataBoss uploadFile:fileData toServer:urlStr withKey:@"uploadFile" contentType:kDataBossFileTypeJPEG queue:queue andParams:params mplete:^(ASIFormDataRequest *request, NSDictionary *json, NSString *errorMsg) { if (!errorMsg) { //上传成功,处理返回结果 }else{ //上传失败 } }]; ##注意事项 - 发送请求时不要把链接编码成UTF8格式,`DataBoss`在发送请求时会自动加上编码,否则链接含有中文时得到的结果和预期不一样。 - 配合`UITableView`分页查询时,服务器接受的分页参数是`page`和`limit`。 - 常用的代码块(code snippet) - 处理返回结果 if (!errorMsg) { //上传成功,处理返回结果 }else{ //上传失败 } - 在`dealloc`方法中取消请求 for (ASIHTTPRequest *req in queue.operations) { [req clearDelegatesAndCancel]; }