封装业务类
1.什么是业务类?
业务类:专门处理某项业务(事情)
2.业务类的作用?
把一些业务的业务逻辑封装起来,其它类需要处理这些业务的时候,直接调用业务类的方法就可以了
大大减少了其它类中的代码量,让代码看起来更整洁,可读性更好
3.业务类的规范
3.1 在类的上面,注明这个类的功能(作用)
让其它人一看到这个类就知道是干什么用的,减少沟通成本
1 // Created by XT on 16/7/31. 2 // Copyright © 2016年 XT. All rights reserved. 3 // 专门处理文件 (标注方式一) 4 5 /** 6 *专门处理文件 (标注方式二) 7 */ 8 @interface XTFileManager : NSObject
3.2 每个方法或属性,都需要使用文档注释
让其他人能快速掌握这个类怎么用,减少沟通成本
/**
*
*作用:指定一个文件夹路径,获取文件夹尺寸
*参数(directoryPath):文件夹路径
*返回值:文件夹尺寸
*/
+ (NSInteger)getSizeOfDirectoryPath:(NSString *)directoryPath;
3.3 每个方法一定要严谨
如果别人不按照方法的规定方式来使用,就报错(抛异常),这样别人就不会认为是方法的问题,能更好的处理错误
例如做一些必要的判断:判断传入的内容不是我们需要的格式,就抛异常
1 // 判断下是否是隐藏文件 2 if ([subPath hasPrefix:@".DS"]) continue; 3 // 是否是文件夹 4 BOOL isDirectory; 5 // 判断文件是否存在,并且是否是文件夹 6 [mgr fileExistsAtPath:filePath isDirectory:&isDirectory]; 7 if (isDirectory) continue;
3.4 怎么抛异常?
1 if (!isExist || !isDirectory) { 2 // 抛异常:NSException 3 // name:异常名称 4 // reason:异常原因 5 方式一: //NSException *excp = [NSException exceptionWithName:@"FileError" reason:@"笨蛋,传入的路径可 6 能为空,或者不是文件夹路径,仔细好好检查吧" userInfo:nil]; 7 //[excp raise]; 8 方式二:@throw [NSException exceptionWithName:@"FileError" reason:@"笨蛋,传入的路径可能为空,或者不 9 是文件夹路径,仔细好好检查吧" userInfo:nil]; 10 }
4.怎么封装业务类?
4.1第一种方法:常规方法封装,直接把方法的声明和实现拷贝到业务类中
缺点: 计算文件夹缓存尺寸,如果文件里面子文件比较多,比较耗时
1 + (void)removeDirectory:(NSString *)directoryPath 2 { 3 NSFileManager *mgr = [NSFileManager defaultManager]; 4 BOOL isDirectory; 5 BOOL isExist = [mgr fileExistsAtPath:directoryPath isDirectory:&isDirectory]; 6 7 if (!isExist || !isDirectory) { 8 // 抛异常:NSException 9 @throw [NSException exceptionWithName:@"FileError" reason:@"笨蛋,传入的路径可能为空,或者不是文 10 件夹路径,仔细好好检查吧" userInfo:nil]; 11 } 12 // 1.删除Cache文件夹 13 [mgr removeItemAtPath:directoryPath error:nil]; 14 // 2.创建新Cache文件夹 15 [mgr createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil]; 16 } 17 18 + (NSInteger)getSizeOfDirectoryPath:(NSString *)directoryPath 19 { 20 // 1.获取文件管理者对象 21 NSFileManager *mgr = [NSFileManager defaultManager]; 22 // 判断传入文件夹路径存在 23 BOOL isDirectory; 24 BOOL isExist = [mgr fileExistsAtPath:directoryPath isDirectory:&isDirectory]; 25 26 if (!isExist || !isDirectory) { 27 // 抛异常:NSException 28 // name:异常名称 29 // reason:异常原因 30 //NSException *excp = [NSException exceptionWithName:@"FileError" reason:@"笨蛋,传入的路径可能为 31 空,或者不是文件夹路径,仔细好好检查吧" userInfo:nil]; 32 // [excp raise]; 33 @throw [NSException exceptionWithName:@"FileError" reason:@"笨蛋,传入的路径可能为空,或者不是文件 34 夹路径,仔细好好检查吧" userInfo:nil]; 35 } 36 NSInteger totalSize = 0; 37 // 2.获取所有文件(传递文件夹路径) 38 // Path:文件夹路径 39 // subpathsAtPath:获取一个文件夹中所有子路径,包含多级路径 40 NSArray *subPaths = [mgr subpathsAtPath:directoryPath]; 41 // 3.遍历所有文件 42 for (NSString *subPath in subPaths) { 43 // 4.拼接完整文件名 44 NSString *filePath = [directoryPath stringByAppendingPathComponent:subPath]; 45 // 判断下是否是隐藏文件 46 if ([subPath hasPrefix:@".DS"]) continue; 47 // 是否是文件夹 48 BOOL isDirectory; 49 // 判断文件是否存在,并且是否是文件夹 50 [mgr fileExistsAtPath:filePath isDirectory:&isDirectory]; 51 if (isDirectory) continue; 52 // 5.attributesOfItemAtPath:传入文件全路径,就能获取文件属性 53 NSDictionary *attr = [mgr attributesOfItemAtPath:filePath error:nil]; 54 // 6.把文件尺寸累加 55 totalSize += [attr fileSize]; 56 } 57 return totalSize; 58 } 59
4.2 第二种方法:block封装业务类 开启子线程,把耗时操作放到子线程中执行
注意:刷新UI的操作一定要回到主线程执行 ,
用block作为参数,开启异步任务,一定不要返回数据
4.3 为什么使用block作为参数,开启异步任务,一定不要返回数据?
异步函数的特点:
01 具备开线程的能力
02 执行任务的方式:异步
异步执行:我开始执行后,可以不用等我执行完,就执行后面的任务
由于异步函数异步执行,如果有返回值,返回值要放到主线程中执行,
那么执行到异步函数的时候,会直接跳过异步函数执行返回操作,这个时候返回值还没计算出来,会造成数据错乱
4.4 怎么解决block作为参数,外界需要返回值的问题?
让带有参数的block 作为参数,把需要返回的数据,赋值给block的参数,让blcok传递出去就就可以了
4.5 block作为参数的格式怎么写?
如果不会的话,就把AFN里面的block参数拷过来改一下
1 - (NSURLSessionDataTask *)GET:(NSString *)URLString 2 parameters:(id)parameters 3 progress:(void (^)(NSProgress * _Nonnull))downloadProgress 4 success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 5 failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 6 7 8 // 异步任务,不要返回数据 9 + (void)getSizeOfDirectoryPath:(NSString *)directoryPath completion:(void (^)(NSInteger totalSize))completion 10 { 11 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 12 // 子线程执行 13 // 1.获取文件管理者对象 14 NSFileManager *mgr = [NSFileManager defaultManager]; 15 // 判断传入文件夹路径存在 16 BOOL isDirectory; 17 BOOL isExist = [mgr fileExistsAtPath:directoryPath isDirectory:&isDirectory]; 18 19 if (!isExist || !isDirectory) { 20 @throw [NSException exceptionWithName:@"FileError" reason:@"笨蛋,传入的路径可能为空,或者不是文件夹路径,仔细好好检查吧" userInfo:nil]; 21 } 22 NSInteger totalSize = 0; 23 24 // 2.获取所有文件(传递文件夹路径) 25 NSArray *subPaths = [mgr subpathsAtPath:directoryPath]; 26 // 3.遍历所有文件 27 for (NSString *subPath in subPaths) { 28 // 4.拼接完整文件名 29 NSString *filePath = [directoryPath stringByAppendingPathComponent:subPath]; 30 31 // 判断下是否是隐藏文件 32 if ([subPath hasPrefix:@".DS"]) continue; 33 // 是否是文件夹 34 BOOL isDirectory; 35 // 判断文件是否存在,并且是否是文件夹 36 [mgr fileExistsAtPath:filePath isDirectory:&isDirectory]; 37 if (isDirectory) continue; 38 // 5.attributesOfItemAtPath:传入文件全路径,就能获取文件属性 39 NSDictionary *attr = [mgr attributesOfItemAtPath:filePath error:nil]; 40 // 6.把文件尺寸累加 41 totalSize += [attr fileSize]; 42 } 43 // 一定要记得回到主线程 44 dispatch_sync(dispatch_get_main_queue(), ^{ 45 if (completion) { 46 注意:()内可以写这个方法定义的任何值,但要和block的参数类型相同,最后括号内的值会传给Block的参数 47 completion(totalSize); 48 } 49 }); 50 }); 51 }