RBEFireworks 是一个功能丰富且灵活的库。它处理网络组件的常见需求,使得网络请求的编程变得更加容易。基于 AFNetworking3.x(NSURLSession),它达到了更高的抽象级别,并参考了 YTKNetwork 的启发性思想。
在此特别感谢 AFNetworking 和 YTKNetwork,因为您的开源资源对于社区来说是无穷无尽的财富。
RBEFireworks 架构设计的原则是简洁,这使得您更易使用。它感觉就像原生 Apple 库,只要您有 NSURLSession 和 NSURLRequest 的知识,这个库就可以非常迅速地全面为您服务。它将网络请求抽象成全新对象,提供强大的可表达性,并且非常方便重用。
RBEFireworks 希望您的网络请求像烟花一样绽放,并能成为永恒的回忆!
iOS8.0+
libsqlite3.tbd
$ pod RBEFireworks
在使用 RBEFireworks 之前,您需要配置 URL 设置。您可以设置基础 URL 或设置 CDN URL。
[RBEFireworkAdapter sharedInstance].baseURL = @"DemoProjectBaseURL";
[RBEFireworkAdapter sharedInstance].CDNURL = @"DemoProjectCDNURL";
要恢复GET请求,您应该提供相对URL。
RBEFirework *firework = [[RBEFirework alloc] initWithRelativeURL:@"demo"];
[firework resume];
要恢复POST请求。要恢复不同的HTTP方法请求,只需提供不同的枚举值。
RBEFirework *firework = [[RBEFirework alloc] initWithRelativeURL:@"demo"
parameters:@{@"demo" : @"demo"}
HTTPMethod:RBEHTTPMethodPost];
[firework resumeWithSuccessBlock:^(RBEFirework * _Nonnull responseFirework) {
//succes to do...
} failureBlock:^(RBEFirework * _Nonnull responseFirework) {
//failure to do...
}];
要恢复链式请求,您应该提供一个包含请求的数组。链式请求按照数组顺序执行请求。如果一个请求失败,则不会执行后续请求。
RBEFirework *demoOne = [[RBEFirework alloc] initWithRelativeURL:@"demoOne"];
RBEFirework *demoTwo = [[RBEFirework alloc] initWithRelativeURL:@"demoTwo"];
RBEFirework *demoThree = [[RBEFirework alloc] initWithRelativeURL:@"demoThree"];
RBEChainFirework *chain = [[RBEChainFirework alloc] initWithFireworkArray:@[demoOne, demoTwo, demoThree]];
[chain resumeWithSuccessBlock:^(RBEChainFirework * _Nonnull chainFirework) {
RBEFirework *successOne = [chainFirework.fireworkArr firstObject];
NSDictionary *successDicOne = successOne.responseObject;
if (successDicOne) {
//first successed...
}
RBEFirework *successTwo = chainFirework.fireworkArr[1];
NSDictionary *successDicTwo = successTwo.responseObject;
if (successDicTwo) {
//second successed...
}
RBEFirework *successThree = [chainFirework.fireworkArr lastObject];
NSDictionary *successDicThree = successThree.responseObject;
if (successDicThree) {
//third successed...
}
} failureBlock:^(RBEChainFirework * _Nonnull chainFirework, RBEFirework * _Nonnull failedFirework) {
if ([failedFirework isEqualToFirework:[chainFirework.fireworkArr firstObject]]) {
//first failed...
} else if ([failedFirework isEqualToFirework:chainFirework.fireworkArr[1]]) {
//second failed...
} else {
//third failed...
}
}];
要恢复批量请求,除了请求数组之外,您还需要决定如果某个请求失败,是否取消其他请求。默认为否。
RBEFirework *demoOne = [[RBEFirework alloc] initWithRelativeURL:@"demoOne"];
RBEFirework *demoTwo = [[RBEFirework alloc] initWithRelativeURL:@"demoTwo"];
RBEFirework *demoThree = [[RBEFirework alloc] initWithRelativeURL:@"demoThree"];
[demoOne setSuccessBlock:^(RBEFirework * _Nonnull responseFirework) {
//first successed...
} failureBlock:^(RBEFirework * _Nonnull responseFirework) {
//first failed...
}];
[demoTwo setSuccessBlock:^(RBEFirework * _Nonnull responseFirework) {
//second successed...
} failureBlock:^(RBEFirework * _Nonnull responseFirework) {
//second failed...
}];
[demoThree setSuccessBlock:^(RBEFirework * _Nonnull responseFirework) {
//third successed...
} failureBlock:^(RBEFirework * _Nonnull responseFirework) {
//third failed...
}];
RBEBatchFirework *batch = [[RBEBatchFirework alloc] initWithFireworkArray:@[demoOne, demoTwo, demoThree] shouldCancelAllFireworkIfOneFireworkFailed:NO];
[batch resume];
如果您偏好回调函数,则可以使用此协议组。
//Firework success
- (void)fireworkFinished:(RBEFirework *)firework {}
//Firework fail
- (void)fireworkFailed:(RBEFirework *)firework {}
//Chain Firework success
- (void)chainFireworkFinished:(RBEChainFirework *)chainFirework {}
//Chain Firework fail
- (void)chainFireworkFailed:(RBEChainFirework *)chainFirework failedFirework:(RBEFirework *)firework {}
//Batch Firework success
- (void)batchFireworkFinished:(RBEBatchFirework *)batchFirework {}
//Batch Firework fail
- (void)batchFireworkFailed:(RBEBatchFirework *)batchFirework failedFireworks:(NSArray<RBEFirework *> *)failedFireworks {}
您可以通过遵守 RBEURLAdapterProtocol 并实现 adaptedURL: 函数来统一过滤URL。
您也可以通过遵守 RBEParametersAdapterProtocol 并实现 adaptedParametersWithOriginalParameters: 函数来统一过滤参数。
@interface DemoURLFilter : NSObject <RBEURLAdapterProtocol>
@end
@implementation DemoURLFilter
- (NSString *)adaptedURL:(NSString *)originURL {
if ([originURL hasPrefix:@"demo"]) {
return [originURL stringByAppendingString:@"/v1"];
} else {
return originURL;
}
}
@end
@interface DemoParametersFilter : NSObject <RBEParametersAdapterProtocol>
@end
@implementation DemoParametersFilter
- (id)adaptedParametersWithOriginalParameters:(id)parameters {
if (parameters) {
NSMutableDictionary *paraDic = parameters;
[paraDic setObject:@(1) forKey:@"type"];
parameters = paraDic;
}else {
parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:@(1) forKey:@"type"];
}
return parameters;
}
@end
然后编写以下代码
//Adapte Parameters
DemoParametersFilter *paramFilter = [[DemoParametersFilter alloc] init];
[[RBEFireworkAdapter sharedInstance] addParamterAdapters:paramFilter];
//Adapte URL
DemoURLFilter *URLFilter = [[DemoURLFilter alloc] init];
[[RBEFireworkAdapter sharedInstance] addURLAdapters:URLFilter];
您还可以统一决定请求调用成功、失败或忽略。如果您决定忽略请求,请求将不会执行成功的完成块或失败的完成块。
[RBEFireworkAdapter sharedInstance].validateBlock = ^(RBEFirework *responseFirework) {
RBEFireworkResponseType responseType = RBEFireworkResponseTypeSuccess;
NSDictionary *responseDic = responseFirework.responseObject;
if (responseDic) {
NSNumber *code = responseDic[@"code"];
if ([code isEqualToNumber:@0]) {
//success
} else if ([code isEqualToNumber:@1]) {
responseType = RBEFireworkResponseTypeFailure;
} else {
responseType = RBEFireworkResponseTypeIgnore;
}
}
return responseType;
};
您可以通过RBEFireworkAdapter设置或获取Cookie。
[[RBEFireworkAdapter sharedInstance] setCookieWithCookieDomain:@".demo.com"
cookieOriginUrl:nil
cookieName:@"demo"
cookieValue:@"demo_value"
cookiePath:@"/"
cookieVersion:nil
cookieExpires:nil];
NSHTTPCookie *cookie = [[RBEFireworkAdapter sharedInstance] cookieWithcookieName:@"demo"];
RBEFireworks中存在两种缓存模式。一种是HTTP缓存模式,另一种是新鲜度缓存模式。您可以通过更改 cachePattern 属性来影响缓存模式。
HTTP缓存模式使用 NSURLCache 实现,基本上就是根据HTTP标准缓存请求。您也可以更改 RBEFireworkAdapter 的 customCachedURLResponse 属性以提供自定义实现。
新鲜度缓存模式使用 RBECache 实现,您需要更改 cacheFreshnessInSecond 属性来提供缓存的存活时间,单位为秒。如果缓存未过期,则表示缓存是新鲜的,请求将不会实际恢复。如果缓存已过期,则表示缓存已过时,请求将实际恢复。
或者,您可以将 cachePattern 属性更改为 RBECachePatternNone,以禁用任何模式缓存。默认为 RBECachePatternNone。
您应该通过 RBEFireworkAdapter 启用任何模式缓存。您需要提供缓存的目录,以及在内存和磁盘中的缓存容量。尽管,HTTP缓存模式的容量单位为字节,而新鲜度缓存模式的容量单位为要缓存的请求数量。
NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
//For Freshness Cache
NSString *freshnessCacheDir = [cacheDirectory stringByAppendingPathComponent:@"FreshnessCache"];
[[RBEFireworkAdapter sharedInstance] enableCacheWithFreshnessCachePatternDirectory:freshnessCacheDir freshnessMemoryCount:20 freshnessDiskCapacity:10 * 1024 * 1024];
//For HTTP Cache
NSString *HTTPCacheDir = [cacheDirectory stringByAppendingPathComponent:@"HTTPCache"];
[[RBEFireworkAdapter sharedInstance] enableCacheWithHTTPCachePatternDirectory:HTTPCacheDir HTTPMemoryCapacity:2 * 1024 * 1024 HTTPDiskCapacity:10 * 1024 * 1024];
清除所有缓存或清除内存中的缓存。
//clear memory cache
[[RBEFireworkAdapter sharedInstance] purgeInMemoryCache];
//clear memory cache and disk cache
[[RBEFireworkAdapter sharedInstance] purgeAllCache];
您还可以通过调用 cachedObject 函数来获取请求的缓存。
RBEFirework *demoOne = [[RBEFirework alloc] initWithRelativeURL:@"demoOne"];
id cachedObject = demoOne.cachedObject;
if (cachedObject) {
//cache to do...
}
您可以使用 RBEUploadFirework 上传数据。您初始化 RBEUploadFirework 提供的URL不是相对URL,而是绝对URL。RBEUploadFirework 使用 AFNetworking 的多部分/表单数据上传实现。
您可以为上传提供文件URL、数据 NSInputStream、数据 NSData 和 multipart/form-data 请求的正文。
RBEUploadFirework *upload = [[RBEUploadFirework alloc] initWithUploadURL:@"demo"];
[upload uploadWithFileURL:[NSURL URLWithString:@"demoURL"]
name:@"demo"
fileName:@"demoFileName"
mimeType:@"demoMimeType"];
您可以使用 RBEDownloadFirework 恢复下载。您初始化 RBEDownloadFirework 提供的URL不是相对URL,而是绝对URL。
苹果的本地实现持续下载必须满足以下条件
RBEFireworks 实现的持续下载不获取 ETag 或 Last-Modified
您可以将 isProvideETagOrLastModified 属性更改为指定。默认为 YES。
RBEDownloadFirework *download = [[RBEDownloadFirework alloc] initWithDownloadURL:@"demo" destinationPath:@"demoDestinationPath"];
//Employ NSURLSession downloadTaskWithResumeData API or self-Implementaion
download.isProvideETagOrLastModified = YES;
[download resumeWithSuccessBlock:^(RBEFirework * _Nonnull responseFirework) {
NSString *path = [download downloadedContentPath];
if (path) {
//Get path to do...
}
} failureBlock:^(RBEFirework * _Nonnull responseFirework) {
//failure to do...
}];
成功后,通过调用downloadedContentPath获取实际下载内容路径。如果无法将下载内容写入您提供的路径,则下载内容将写入临时路径。因此,downloadedContentPath返回的路径可能不是您提供的路径。
RBEUploadFirework和RBEDownloadFirework可以通过修改progressBlock属性来获取进度回调。
firework.progressBlock = ^(NSProgress *progress) {
//progress to do...
};
暂停和取消请求。
[firework suspend];
[firework cancel];
您可以通过调用breakChain函数来断开链式请求。
RBEFirework *demoOne = [[RBEFirework alloc] initWithRelativeURL:@"demoOne"];
[demoOne setSuccessBlock:^(RBEFirework * _Nonnull responseFirework) {
NSDictionary *respondeDic = responseFirework.responseObject;
if (respondeDic[@"demo"]) {
[responseFirework breakChain];
}
} failureBlock:^(RBEFirework * _Nonnull responseFirework) {
//failure to do
}];
RBEFirework *demoTwo = [[RBEFirework alloc] initWithRelativeURL:@"demoTwo"];
RBEChainFirework *chain = [[RBEChainFirework alloc] initWithFireworkArray:@[demoOne, demoThree]];
[chain resume];
您可以通过验证服务返回的响应类型是否符合您的预期。数据的名称应映射到数据类型。如果不符合,请求将失败。
firework.responseValidator = @[@{@"demoId" : [NSString class],
@"demoTime" : [NSNumber class],
@"demoStuff" : @{
@"demoStuffId" : [NSString class],
@"demoStuffContent" : [NSString class]
}
}];
您可以在恢复请求之前、取消请求之前、暂停请求之前、请求执行完成块之前或之后执行任何操作。您只需遵循RBEFireworkAccessoryProtocol并实现任意函数。例如,您可以编写以下代码来显示加载状态
@interface DemoFireworkAccessory : NSObject <RBEFireworkAccessoryProtocol>
@property (nonatomic, strong) UIActivityIndicatorView *indicator;
+ (instancetype)accessory;
- (void)fireworkWillResume:(RBEFirework *)firework;
- (void)fireworkWillComplete:(RBEFirework *)firework;
@end
@implementation DemoFireworkAccessory
+ (instancetype)accessory {
DemoFireworkAccessory *accessory = [[DemoFireworkAccessory alloc] init];
accessory.indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
return accessory;
}
- (void)fireworkWillResume:(RBEFirework *)firework {
[self.indicator startAnimating];
}
- (void)fireworkWillComplete:(RBEFirework *)firework {
[self.indicator stopAnimating];
}
@end
然后编写以下代码
DemoFireworkAccessory *accessory = [DemoFireworkAccessory accessory];
[firework addAccessory:accessory];
您可以通过修改customRequest属性来恢复自定义请求,您提供的自定义请求将忽略RBEFirework的其他配置,除了成功和失败回调。
firework.customRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"firework"]];
您可以通过调用RBEFireworkAdapter的以下函数来取消所有请求。这将导致NSURLSession对应配置类型的调用finishTasksAndInvalidate或invalidateAndCancel函数。
- (void)cancelAllRBEFireworkInConfigurationTpye:(RBESessionConfigurationType)configurationType allowOutstandingTaskFinish:(BOOL)isAllow;
除了这些,您仍然可以配置AFNetworking。
@property (nonatomic, assign) RBEFireworkRequestSerializerType requestSerializerType;
@property (nonatomic, assign) RBEFireworkResponseSerializerType responseSerializerType;
//Default is application/json text/json text/javascript
@property (nonatomic, strong) NSSet<NSString *> *acceptableContentTypes;
//Default is No
@property (nonatomic, assign) BOOL allowInvalidCertificates;
第一个是请求序列化类型,默认为HTTP。第二个是响应标准化类型,默认为JSON。第三个是响应接受的内容类型,默认为application/json,text/json,text/javascript。第四个是是否允许无效的证书,默认为NO。
还有许多其他属性可进行配置,它们直接会影响NSMutableURLRequest。
@property (nonatomic, assign) NSTimeInterval timeoutInterval;
@property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;
@property (nonatomic, assign) BOOL allowsCellularAccess;
@property (nonatomic, assign) BOOL HTTPShouldHandleCookies;
@property (nonatomic, assign) BOOL HTTPShouldUsePipelining;
配置类型影响请求对应的NSURLSessionConfiguration。
@property (nonatomic, assign) RBESessionConfigurationType sessionConfigurationType;
标签
@property (nonatomic, assign) NSInteger tag;
@property (nullable, nonatomic, strong) NSDictionary *userInfo;
更改HTTP头
- (void)setAuthenticationHeaderFieldWithUserName:(NSString *)userName password:(NSString *)password;
- (void)setHeaderField:(NSDictionary<NSString *, NSString *> *)headerField;
如果您想获取请求的信息,只需使用NSLog。
以上代码也在示例中演示。
最重要的是,享受乐趣!