小说绘上架版本

This commit is contained in:
xtfei2011
2021-02-07 11:24:08 +08:00
commit ee5c1c8b12
1762 changed files with 115892 additions and 0 deletions
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>-1</key>
<string>无效的URL地址</string>
<key>-999</key>
<string>无效的URL地址</string>
<key>-1000</key>
<string>无效的URL地址</string>
<key>-1001</key>
<string>网络连接超时</string>
<key>-1002</key>
<string>不支持的URL地址</string>
<key>-1003</key>
<string>找不到服务器</string>
<key>-1004</key>
<string>连接不上服务器</string>
<key>-1005</key>
<string>网络连接异常</string>
<key>-1006</key>
<string>DNS查询失败</string>
<key>-1007</key>
<string>HTTP请求重定向</string>
<key>-1008</key>
<string>资源不可用</string>
<key>-1009</key>
<string>当前无网络连接</string>
<key>-1010</key>
<string>重定向到不存在的位置</string>
<key>-1011</key>
<string>服务器响应异常</string>
<key>-1012</key>
<string>用户取消授权</string>
<key>-1013</key>
<string>需要用户授权</string>
<key>-1014</key>
<string>0字节资源</string>
<key>-1015</key>
<string>无法解码原始数据</string>
<key>-1016</key>
<string>无法解码内容数据</string>
<key>-1017</key>
<string>无法解析响应</string>
<key>-1018</key>
<string>国际漫游关闭</string>
<key>-1019</key>
<string>被叫激活</string>
<key>-1020</key>
<string>数据不被允许</string>
<key>-1021</key>
<string>请求体</string>
<key>-1100</key>
<string>文件不存在</string>
<key>-1101</key>
<string>文件是个目录</string>
<key>-1102</key>
<string>无读取文件权限</string>
<key>-1103</key>
<string>请求数据长度超出最大限度</string>
<key>-1200</key>
<string>安全连接失败</string>
<key>-1201</key>
<string>服务器证书失效</string>
<key>-1202</key>
<string>不被信任的服务器证书</string>
<key>-1203</key>
<string>未知Root的服务器证书</string>
<key>-1204</key>
<string>服务器证书未生效</string>
<key>-1205</key>
<string>客户端证书被拒</string>
<key>-1206</key>
<string>需要客户端证书</string>
<key>-2000</key>
<string>无法从网络获取</string>
<key>-3000</key>
<string>无法创建文件</string>
<key>-3001</key>
<string>无法打开文件</string>
<key>-3002</key>
<string>无法关闭文件</string>
<key>-3003</key>
<string>无法写入文件</string>
<key>-3004</key>
<string>无法删除文件</string>
<key>-3005</key>
<string>无法移动文件</string>
<key>-3006</key>
<string>下载解码数据失败</string>
<key>-3007</key>
<string>下载解码数据失败</string>
</dict>
</plist>
@@ -0,0 +1,63 @@
//
// TFNetworkTools.h
// WXReader
//
// Created by 谢腾飞 on 2020/12/3.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
@class TFNetworkRequestModel;
NS_ASSUME_NONNULL_BEGIN
typedef void(^ _Nullable requestSuccessBlock) (BOOL isSuccess, id _Nullable t_model, TFNetworkRequestModel *requestModel);
typedef void(^ _Nullable quickRequestSuccessBlock) (BOOL isSuccess, id _Nullable t_model, BOOL isCache, TFNetworkRequestModel *requestModel);
typedef void(^ _Nullable requestFailedBlock) (NSURLSessionDataTask * _Nullable task, NSError *error);
@interface TFNetworkTools : UIViewController
/// POST request
/// @param url 请求地址
/// @param parameters 请求参数
/// @param model 数据类型,设置为nil时返回的t_model将是原始字典
/// @param success 成功回调
/// @param failure 失败回调
+ (void)POST:(NSString *)url parameters:(NSDictionary * _Nullable)parameters model:(Class _Nullable)model success:(requestSuccessBlock)success failure:(requestFailedBlock)failure;
/// POST request,带缓存
/// @param url 请求地址
/// @param parameters 请求参数
/// @param model 数据类型,设置为nil时返回的t_model将是原始字典
/// @param success 成功回调
/// @param failure 失败回调
+ (void)POSTQuick:(NSString *)url parameters:(NSDictionary * _Nullable)parameters model:(Class _Nullable)model success:(quickRequestSuccessBlock)success failure:(requestFailedBlock)failure;
/// POST request,可以设置回调队列
/// @param url 请求地址
/// @param parameters 请求参数
/// @param model 数据类型,设置为nil时返回的t_model将是原始字典
/// @param completionQueue 回调队列
/// @param success 成功回调
/// @param failure 失败回调
+ (void)POST:(NSString *)url parameters:(NSDictionary * _Nullable)parameters model:(Class _Nullable)model completionQueue:(dispatch_queue_t)completionQueue success:(requestSuccessBlock)success failure:(requestFailedBlock)failure;
@end
@interface TFNetworkRequestModel : NSObject
@property (nonatomic ,strong ,nullable) NSURLSessionDataTask *task;
@property (nonatomic ,strong ,nullable) NSDictionary *data;
@property (nonatomic ,strong ,nullable) NSString *msg;
@property (nonatomic ,assign) NSInteger code;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,162 @@
//
// TFNetworkTools.m
// WXReader
//
// Created by 谢腾飞 on 2020/12/3.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import "TFNetworkTools.h"
#import <XHNetworkCache.h>
#import "CommonCrypto/CommonDigest.h"
#import "NSString+TFExtension.h"
// 请求成功
#define Request_Success_From(x) [[NSString stringWithFormat:@"%@",[x objectForKey:@"code"]] isEqualToString:@"0"]
static NSString * const kCode = @"code";
static NSString * const kMsg = @"msg";
static NSString * const kData = @"data";
@implementation TFNetworkTools
+ (void)POST:(NSString *)url parameters:(NSDictionary * _Nullable)parameters model:(Class _Nullable)model success:(requestSuccessBlock)success failure:(requestFailedBlock)failure
{
[self POST:url parameters:parameters model:model completionQueue:dispatch_get_main_queue() success:success failure:failure];
}
+ (void)POSTQuick:(NSString *)url parameters:(NSDictionary * _Nullable)parameters model:(Class _Nullable)model success:(quickRequestSuccessBlock)success failure:(requestFailedBlock)failure
{
// 读取缓存数据,若存在则返回缓存数据
NSString *prefix = [url stringByAppendingString:TFLanguageManager.serverLocalized];
if ([XHNetworkCache checkCacheWithURL:prefix params:parameters]) {
NSDictionary *dic = [NSDictionary dictionaryWithDictionary:[XHNetworkCache cacheJsonWithURL:prefix params:parameters]];
TFNetworkRequestModel *requestModel = [[TFNetworkRequestModel alloc] init];
requestModel.data = dic;
dispatch_async(dispatch_get_main_queue(), ^{
!success ?: success(YES, model ? [model modelWithDictionary:dic] : dic, YES, requestModel);
});
}
[self POST:url parameters:parameters model:model completionQueue:dispatch_get_main_queue() success:^(BOOL isSuccess, id _Nullable t_model, TFNetworkRequestModel * _Nonnull requestModel) {
if (isSuccess) {
[XHNetworkCache save_asyncJsonResponseToCacheFile:model ? [t_model modelToJSONObject] : requestModel.data andURL:prefix params:parameters completed:nil];
}
!success ?: success(isSuccess, t_model, NO, requestModel);
} failure:failure];
}
+ (void)POST:(NSString *)url parameters:(NSDictionary *)parameters model:(Class _Nullable)model completionQueue:(dispatch_queue_t)completionQueue success:(requestSuccessBlock)success failure:(requestFailedBlock)failure
{
// 没有网络则直接返回
if (![TFNetworkManager networkingStatus]) return;
TFLog(@"--->请求地址URL%@",url);
url = [APIURL stringByAppendingString:url];
url = url.networkUrl;
parameters = [self integrationRequestWithParameters:parameters ?: @{}];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
securityPolicy.allowInvalidCertificates = YES;
securityPolicy.validatesDomainName = NO;
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy = securityPolicy;
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setTimeoutInterval:kOvertime];
manager.completionQueue = completionQueue;
TFLog(@"--->请求参数%@",manager);
[manager POST:url parameters:parameters headers:@{@"Content-Type":@"application/json", @"Accept":@"application/json"} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
TFLog(@"--->请求成功返回%@",responseObject);
NSDictionary *dic = [NSDictionary dictionaryWithDictionary:responseObject];
TFNetworkRequestModel *requestModel = [[TFNetworkRequestModel alloc] init];
requestModel.task = task;
requestModel.data = dic[kData];
requestModel.msg = [NSString stringWithFormat:@"%@", dic[kMsg]];
requestModel.code = [dic[kCode] integerValue];
if (requestModel.code != 704) { // 704 请求重复排除
!success ?: success(Request_Success_From(dic), model ? [model modelWithDictionary:dic[kData]] : dic, requestModel);
}
[manager.session finishTasksAndInvalidate];
if (requestModel.code == 301 || requestModel.code == 302) {
[kNotification postNotificationName:Notification_Logout object:nil];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
TFLog(@"--->请求失败返回:%@",error);
!failure ?: failure(task, error);
[manager.session finishTasksAndInvalidate];
}];
}
+ (NSString *)authString:(NSDictionary *)params
{
NSArray *allKeys = params.allKeys;
allKeys = [allKeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
NSMutableArray *signArray = [NSMutableArray array];
for (NSString *key in allKeys) {
NSString *keyValue = [NSString stringWithFormat:@"%@=%@", key, params[key]];
[signArray addObject:keyValue];
}
NSString *signString = [signArray componentsJoinedByString:@"&"];
signString = [NSString stringWithFormat:@"%@%@%@", app_key, signString, secret_key];
return [self stringToMD5:signString];
}
+ (NSDictionary *)integrationRequestWithParameters:(NSDictionary *)parameters
{
NSMutableDictionary *integrationParament = [NSMutableDictionary dictionaryWithDictionary:parameters];
[integrationParament setObject:App_Ver forKey:@"ver"];
[integrationParament setObject:@"1" forKey:@"osType"];
[integrationParament setObject:@"1" forKey:@"appId"];
[integrationParament setObject:@"1" forKey:@"product"];
[integrationParament setObject:@"AppStore" forKey:@"marketChannel"];
[integrationParament setObject:[[NSBundle mainBundle] bundleIdentifier] forKey:@"packageName"];
[integrationParament setObject:[TFUtilsHelper getTimeStamp] ? : @"" forKey:@"time"];
[integrationParament setObject:[TFUtilsHelper getUDID] ? : @"" forKey:@"udid"];
[integrationParament setObject:[TFUtilsHelper getSystemVersion] ? : @"" forKey:@"sysVer"];
[integrationParament setObject:[TFUtilsHelper getCurrentDeviceModel] ? : @"" forKey:@"phoneModel"];
[integrationParament setObject:[TFUserInfoManager shareInstance].token forKey:@"token"];
[integrationParament setObject:@"zh" forKey:@"language"];
// [integrationParament setObject:[TFLanguageManager serverLocalized] forKey:@"language"];
[integrationParament setObject:[self authString:integrationParament] ? : @"" forKey:@"sign"];
return integrationParament;
}
+ (NSString *)stringToMD5:(NSString *)inputStr
{
const char *cStr = [inputStr UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr,(CC_LONG)strlen(cStr), result);
NSString *resultStr = [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]
];
return [resultStr lowercaseString];
}
@end
@implementation TFNetworkRequestModel
@end
@@ -0,0 +1,36 @@
//
// TFURLProtocol.h
// WXReader
//
// Created by 谢腾飞 on 2020/12/3.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TFURLProtocol : NSURLProtocol
@property (nonatomic ,assign ,readonly) BOOL isSwizzle;
+ (instancetype)sharedInstance;
/// 开始监听
+ (void)startMonitor;
/// 停止监听
+ (void)stopMonitor;
@end
@interface TFSessionConfig : NSObject
+ (void)swizzleSelector;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,197 @@
//
// TFURLProtocol.m
// WXReader
//
// Created by 谢腾飞 on 2020/12/3.
// Copyright © 2020 xtfei_2011@126.com. All rights reserved.
//
#import "TFURLProtocol.h"
#import "AppDelegate.h"
#import <objc/runtime.h>
// 拦截标识符,避免无限循环
static NSString * const kProtocolIdentifier = @"kProtocolIdentifier";
// 默认微信Token请求接口前缀
static NSString * const kDefaultTokenURL = @"https://api.weixin.qq.com/sns/oauth2/access_token?";
@interface TFURLProtocol ()<NSURLConnectionDelegate, NSURLConnectionDataDelegate, NSURLSessionDelegate>
@property (nonatomic ,strong) NSURLSessionDataTask *dataTask;
@property (nonatomic ,strong) NSOperationQueue *sessionDelegateQueue;
@property (nonatomic ,strong) NSURLResponse *response;
@property (nonatomic ,weak) AppDelegate *delegate;
@end
@implementation TFURLProtocol
+ (void)startMonitor
{
[NSURLProtocol registerClass:self];
[self sharedInstance];
[_instance load];
}
+ (void)stopMonitor
{
[NSURLProtocol unregisterClass:self];
[self sharedInstance];
[_instance unload];
}
static TFURLProtocol *_instance;
+ (instancetype)sharedInstance
{
return [[self alloc] init];
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
/// 拦截网络请求
/// @param request 需要拦截的请求
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
if ([NSURLProtocol propertyForKey:kProtocolIdentifier inRequest:request]) {
return NO;
}
// 拦截微信获取Token的网络请求。
dispatch_semaphore_t signal = dispatch_semaphore_create(0);
AppDelegate * __block delegate;
dispatch_async(dispatch_get_main_queue(), ^{
delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
_instance.delegate = delegate;
dispatch_semaphore_signal(signal);
});
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
NSString *prefix = delegate.checkSettingModel.wechatTokenURL ?: kDefaultTokenURL;
if ([request.URL.absoluteString hasPrefix:prefix]) {
NSURLComponents *components = [[NSURLComponents alloc] initWithString:request.URL.absoluteString];
[components.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *name = obj.name;
NSString *value = obj.value;
if ([name isEqualToString:@"code"]) {
delegate.wechatCode = value;
}
}];
return YES;
}
return NO;
}
/// 返回自定义的网络请求
/// @param request 网络请求
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
return [[NSURLRequest alloc] init];
}
// 重写父类的开始加载方法
- (void)startLoading
{
NSURLSessionConfiguration *configuration =
[NSURLSessionConfiguration defaultSessionConfiguration];
self.sessionDelegateQueue = [[NSOperationQueue alloc] init];
self.sessionDelegateQueue.maxConcurrentOperationCount = 1;
self.sessionDelegateQueue.name = @"com.beiwo.queue";
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:self.sessionDelegateQueue];
self.dataTask = [session dataTaskWithRequest:self.request];
[self.dataTask resume];
}
// 结束加载
- (void)stopLoading
{
[self.dataTask cancel];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (!error) {
[self.client URLProtocolDidFinishLoading:self];
} else if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) {
} else {
[self.client URLProtocol:self didFailWithError:error];
}
self.dataTask = nil;
}
// 当服务端返回信息时,这个回调函数会被ULS调用,在这里实现http返回信息的截取
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data
{
[self.client URLProtocol:self didLoadData:data];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
completionHandler(NSURLSessionResponseAllow);
self.response = response;
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler
{
if (response != nil) {
self.response = response;
[[self client] URLProtocol:self wasRedirectedToRequest:request redirectResponse:response];
}
}
- (void)load
{
if (_isSwizzle == YES) return;
_isSwizzle = YES;
[TFSessionConfig swizzleSelector];
}
- (void)unload
{
if (_isSwizzle == NO) return;
_isSwizzle = NO;
[TFSessionConfig swizzleSelector];
}
@end
@implementation TFSessionConfig
+ (void)swizzleSelector
{
Class originCls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");
Method fromMethod = class_getInstanceMethod(originCls, @selector(protocolClasses));
Method toMethed = class_getInstanceMethod(self.class, @selector(protocolClasses));
if (!fromMethod || !toMethed) {
[NSException raise:NSInternalInconsistencyException format:@"无法加载NEURLSessionConfiguration。"];
}
method_exchangeImplementations(fromMethod, toMethed);
}
- (NSArray *)protocolClasses
{
return @[[TFURLProtocol class]];
}
@end