Showing preview only (363K chars total). Download the full file or copy to clipboard to get everything.
Repository: QianKun-HanLin/HLNetworking
Branch: master
Commit: 62d3a7ff6f0e
Files: 78
Total size: 317.4 KB
Directory structure:
gitextract_diowpqpv/
├── .gitignore
├── HLNetworking/
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets/
│ │ └── AppIcon.appiconset/
│ │ └── Contents.json
│ ├── Base.lproj/
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── HLAPICenter+home.h
│ ├── HLAPICenter+home.m
│ ├── Info.plist
│ ├── Source/
│ │ ├── Center/
│ │ │ ├── HLAPICenter.h
│ │ │ ├── HLAPICenter.m
│ │ │ ├── HLAPIMacro.h
│ │ │ ├── HLBaseObjReformer.h
│ │ │ └── HLBaseObjReformer.m
│ │ ├── Config/
│ │ │ ├── HLFormDataConfig.h
│ │ │ ├── HLFormDataConfig.m
│ │ │ ├── HLNetworkConfig.h
│ │ │ ├── HLNetworkConfig.m
│ │ │ ├── HLNetworkConst.h
│ │ │ ├── HLNetworkMacro.h
│ │ │ ├── HLNetworkPolicyConfig.h
│ │ │ ├── HLNetworkPolicyConfig.m
│ │ │ ├── HLNetworkRequestConfig.h
│ │ │ ├── HLNetworkRequestConfig.m
│ │ │ ├── HLNetworkTipsConfig.h
│ │ │ ├── HLNetworkTipsConfig.m
│ │ │ ├── HLSecurityPolicyConfig.h
│ │ │ └── HLSecurityPolicyConfig.m
│ │ ├── Engine/
│ │ │ ├── HLNetworkEngine.h
│ │ │ └── HLNetworkEngine.m
│ │ ├── Generator/
│ │ │ ├── Request/
│ │ │ │ ├── API/
│ │ │ │ │ ├── HLAPIRequest.h
│ │ │ │ │ ├── HLAPIRequest.m
│ │ │ │ │ └── HLAPIRequest_InternalParams.h
│ │ │ │ ├── Base/
│ │ │ │ │ ├── HLURLRequest.h
│ │ │ │ │ ├── HLURLRequest.m
│ │ │ │ │ └── HLURLRequest_InternalParams.h
│ │ │ │ ├── Group/
│ │ │ │ │ ├── HLRequestGroup.h
│ │ │ │ │ └── HLRequestGroup.m
│ │ │ │ └── Task/
│ │ │ │ ├── HLTaskRequest.h
│ │ │ │ ├── HLTaskRequest.m
│ │ │ │ └── HLTaskRequest_InternalParams.h
│ │ │ ├── Response/
│ │ │ │ ├── HLURLResponse.h
│ │ │ │ └── HLURLResponse.m
│ │ │ └── Result/
│ │ │ ├── HLURLResult.h
│ │ │ └── HLURLResult.m
│ │ ├── HLNetworking.h
│ │ ├── Logger/
│ │ │ ├── HLDebugMessage.h
│ │ │ ├── HLDebugMessage.m
│ │ │ ├── HLNetworkLogger.h
│ │ │ ├── HLNetworkLogger.m
│ │ │ ├── HLNetworkLoggerConfig.h
│ │ │ ├── HLNetworkLoggerConfig.m
│ │ │ ├── NSNull+ToDictionary.h
│ │ │ ├── NSNull+ToDictionary.m
│ │ │ ├── UIDevice+deviceInfo.h
│ │ │ ├── UIDevice+deviceInfo.m
│ │ │ └── iPhoneTypeDefine.plist
│ │ └── Manager/
│ │ ├── HLNetworkManager.h
│ │ └── HLNetworkManager.m
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
├── HLNetworking.podspec
├── HLNetworking.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcshareddata/
│ └── xcschemes/
│ └── HLNetworking.xcscheme
├── HLNetworkingTests/
│ ├── HLAPIRequestTest.m
│ ├── HLManagerTests.m
│ ├── HLRequestGroupTests.m
│ ├── HLTaskRequestTest.m
│ ├── HLTestCase.h
│ ├── HLTestCase.m
│ ├── Info.plist
│ └── httpbin.org.cer
├── LICENSE
├── Podfile
├── README.md
└── README_old.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
HLNetworking.xcodeproj/xcuserdata/
HLNetworking.xcworkspace/
Pods/
*.swp
Podfile.lock
.DS_Store
HLNetworking.xcodeproj/project.xcworkspace/xcuserdata/
================================================
FILE: HLNetworking/AppDelegate.h
================================================
//
// AppDelegate.h
// HLNetworking
//
// Created by wangshiyu13 on 2016/9/22.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: HLNetworking/AppDelegate.m
================================================
//
// AppDelegate.m
// HLNetworking
//
// Created by wangshiyu13 on 2016/9/22.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
================================================
FILE: HLNetworking/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: HLNetworking/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
================================================
FILE: HLNetworking/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
================================================
FILE: HLNetworking/HLAPICenter+home.h
================================================
//
// HLAPICenter+home.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLAPICenter.h"
@interface HLAPICenter (home)
HLStrongProperty(home)
@end
================================================
FILE: HLNetworking/HLAPICenter+home.m
================================================
//
// HLAPICenter+home.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLAPICenter+home.h"
@implementation HLAPICenter (home)
HLStrongSynthesize(home, [HLAPIRequest request]
.setMethod(GET)
.setCustomURL(@"get")
.setObjReformerDelegate(self.defaultReformer))
@end
================================================
FILE: HLNetworking/Info.plist
================================================
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>HLNetworking</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.3.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>abc</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>31</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
================================================
FILE: HLNetworking/Source/Center/HLAPICenter.h
================================================
//
// HLAPICenter.h
// HLNetworking+Lovek12
//
// Created by wangshiyu13 on 2016/12/9.
// Copyright © 2016年 mykj. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLBaseObjReformer.h"
#import "HLAPIMacro.h"
@interface HLAPICenter : NSObject
+ (instancetype)defaultCenter;
@property (nonatomic, strong) HLBaseObjReformer *defaultReformer;
@end
================================================
FILE: HLNetworking/Source/Center/HLAPICenter.m
================================================
//
// HLAPICenter.m
// HLNetworking+Lovek12
//
// Created by wangshiyu13 on 2016/12/9.
// Copyright © 2016年 mykj. All rights reserved.
//
#import "HLAPICenter.h"
static HLAPICenter *shared = nil;
@implementation HLAPICenter
- (HLBaseObjReformer *)defaultReformer {
if (!_defaultReformer) {
_defaultReformer = [[HLBaseObjReformer alloc] init];
}
return _defaultReformer;
}
+ (instancetype)defaultCenter {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if(shared == nil) {
shared = [[self alloc] init];
}
});
return shared;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t token;
dispatch_once(&token, ^{
if(shared == nil)
{
shared = [super allocWithZone:zone];
}
});
return shared;
}
- (id)copy {
return self;
}
- (id)mutableCopy {
return self;
}
@end
================================================
FILE: HLNetworking/Source/Center/HLAPIMacro.h
================================================
//
// HLAPIMacro.h
// HLNetworking+Lovek12
//
// Created by wangshiyu13 on 2016/12/10.
// Copyright © 2016年 mykj. All rights reserved.
//
#ifndef HLAPIMacro_h
#define HLAPIMacro_h
#import <objc/runtime.h>
#define metamacro_concat(A, B) \
metamacro_concat_(A, B)
#define metamacro_concat_(A, B) A ## B
#define HLStrongProperty(name) \
@property (nonatomic, strong, setter=set__nonuse__##name:, getter=__nonuse__##name) HLAPIRequest *name; \
+ (HLAPIRequest *)name;
#define HLStrongSynthesize(name, api) \
static void *name##AssociatedKey = #name "associated"; \
- (void)set__nonuse__##name:(HLAPIRequest *)name { \
objc_setAssociatedObject(self, name##AssociatedKey, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC); \
} \
\
- (HLAPIRequest *)__nonuse__##name { \
id _##name = objc_getAssociatedObject(self, name##AssociatedKey); \
if (!_##name) { \
_##name = api; \
} \
return _##name; \
} \
+ (HLAPIRequest *)name { \
return [[self defaultCenter] __nonuse__##name];\
}
#endif /* HLAPIMacro_h */
================================================
FILE: HLNetworking/Source/Center/HLBaseObjReformer.h
================================================
//
// HLBaseObjReformer.h
// HLNetworking+Lovek12
//
// Created by wangshiyu13 on 2016/12/9.
// Copyright © 2016年 mykj. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLAPIRequest.h"
@interface HLBaseObjReformer : NSObject<HLReformerDelegate>
@end
================================================
FILE: HLNetworking/Source/Center/HLBaseObjReformer.m
================================================
//
// HLBaseObjReformer.m
// HLNetworking+Lovek12
//
// Created by wangshiyu13 on 2016/12/9.
// Copyright © 2016年 mykj. All rights reserved.
//
#import "HLBaseObjReformer.h"
#import <YYModel/YYModel.h>
@implementation HLBaseObjReformer
- (id)reformerObject:(id)responseObject andError:(NSError *)error atRequest:(HLAPIRequest *)api {
if (api.objClz && ![NSStringFromClass(api.objClz) isEqualToString:@"NSObject"]) {
if (responseObject) {
return [api.objClz yy_modelWithJSON:responseObject];
}
}
#if DEBUG
NSLog(@"该对象无法转换,api = %@", api);
#endif
return nil;
}
@end
================================================
FILE: HLNetworking/Source/Config/HLFormDataConfig.h
================================================
//
// HLFormDataConfig.h
// HLNetworking
//
// Created by wangshiyu13 on 2016/9/23.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#pragma mark - 用于拼接formData的协议
@protocol HLMultipartFormDataProtocol
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
name:(NSString *)name
error:(NSError * __nullable __autoreleasing *)error;
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
error:(NSError * __nullable __autoreleasing *)error;
- (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream
name:(NSString *)name
fileName:(NSString *)fileName
length:(int64_t)length
mimeType:(NSString *)mimeType;
- (void)appendPartWithFileData:(NSData *)data
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType;
- (void)appendPartWithFormData:(NSData *)data
name:(NSString *)name;
- (void)appendPartWithHeaders:(nullable NSDictionary *)headers
body:(NSData *)body;
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
delay:(NSTimeInterval)delay;
@end
@interface HLFormDataConfig : NSObject
// 用于二进制数据的formData拼接
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithData:(NSData *)data
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType;
// 用于图片数据的formData拼接
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithImage:(UIImage *)image
name:(NSString *)name
fileName:(NSString *)fileName
quality:(CGFloat)quality;
// 用于url所在数据的formData拼接
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithFileURL:(NSURL *)fileURL
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
error:(NSError * __nullable __autoreleasing *)error;
// 用于NSInputStream获取数据的formData拼接
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithInputStream:(nullable NSInputStream *)inputStream
name:(NSString *)name
fileName:(NSString *)fileName
length:(int64_t)length
mimeType:(NSString *)mimeType;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Config/HLFormDataConfig.m
================================================
//
// HLFormDataConfig.m
// HLNetworking
//
// Created by wangshiyu13 on 2016/9/23.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import "HLFormDataConfig.h"
@implementation HLFormDataConfig
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithData:(NSData *)data
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
{
return ^(id<HLMultipartFormDataProtocol> formData) {
[formData appendPartWithFileData:data
name:name
fileName:fileName
mimeType:mimeType];
};
}
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithImage:(UIImage *)image
name:(NSString *)name
fileName:(NSString *)fileName
quality:(CGFloat)quality
{
return ^(id<HLMultipartFormDataProtocol> formData) {
NSData *data;
NSString *mimeType;
if (UIImagePNGRepresentation(image) == nil) {
data = UIImageJPEGRepresentation(image, quality);
mimeType = @"image/jpeg";
}else {
data = UIImagePNGRepresentation(image);
mimeType = @"image/png";
}
[formData appendPartWithFileData:data
name:name
fileName:fileName
mimeType:mimeType];
};
}
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithFileURL:(NSURL *)fileURL
name:(NSString *)name
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
error:(NSError * __nullable __autoreleasing *)error
{
return ^(id<HLMultipartFormDataProtocol> formData) {
[formData appendPartWithFileURL:fileURL
name:name
fileName:fileName
mimeType:mimeType
error:error];
};
}
+ (void (^)(id<HLMultipartFormDataProtocol>))configWithInputStream:(nullable NSInputStream *)inputStream
name:(NSString *)name
fileName:(NSString *)fileName
length:(int64_t)length
mimeType:(NSString *)mimeType {
return ^(id<HLMultipartFormDataProtocol> formData) {
[formData appendPartWithInputStream:inputStream
name:name
fileName:fileName
length:length
mimeType:mimeType];
};
}
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkConfig.h
================================================
//
// HLNetworkConfig.h
// HLPPShop
//
// Created by wangshiyu13 on 2016/9/19.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLSecurityPolicyConfig.h"
#import "HLNetworkTipsConfig.h"
#import "HLNetworkRequestConfig.h"
#import "HLNetworkPolicyConfig.h"
NS_ASSUME_NONNULL_BEGIN
DISPATCH_EXPORT void dispatch_async_main(dispatch_queue_t queue, dispatch_block_t block);
@interface HLNetworkConfig : NSObject<NSCopying>
// 提示相关参数
@property (nonatomic, strong) HLNetworkTipsConfig *tips;
// 请求相关参数
@property (nonatomic, strong) HLNetworkRequestConfig *request;
// 网络策略相关参数
@property (nonatomic, strong) HLNetworkPolicyConfig *policy;
// 安全策略相关参数
@property (nonatomic, strong) HLSecurityPolicyConfig *defaultSecurityPolicy;
// 是否启用reachability,baseURL为domain
@property (nonatomic, assign) BOOL enableReachability;
// 是否开启网络debug日志,该选项会在控制台输出所有网络回调日志,并且在Release模式下无效
@property (nonatomic, assign) BOOL enableGlobalLog;
// 快速构建config
+ (HLNetworkConfig *)config;
// 请使用config
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Config/HLNetworkConfig.m
================================================
//
// HLNetworkConfig.m
// HLPPShop
//
// Created by wangshiyu13 on 2016/9/19.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import "HLNetworkConfig.h"
inline void dispatch_async_main(dispatch_queue_t queue, dispatch_block_t block) {
if (queue) {
dispatch_async(queue, block);
} else {
if (![NSThread isMainThread]) {
dispatch_async(dispatch_get_main_queue(), block);
} else {
block();
}
}
}
@implementation HLNetworkConfig
- (instancetype)init {
self = [super init];
if (self) {
_tips = [HLNetworkTipsConfig config];
_request = [HLNetworkRequestConfig config];
_policy = [HLNetworkPolicyConfig config];
_enableReachability = NO;
_enableGlobalLog = NO;
_defaultSecurityPolicy = [HLSecurityPolicyConfig policyWithPinningMode:HLSSLPinningModeNone];
}
return self;
}
+ (HLNetworkConfig *)config {
return [[self alloc] init];
}
- (id)copyWithZone:(NSZone *)zone {
HLNetworkConfig *config = [[[self class] alloc] init];
if (config) {
config.tips = [_tips copyWithZone:zone];
config.request = [_request copyWithZone:zone];
config.policy = [_policy copyWithZone:zone];
config.defaultSecurityPolicy = [_defaultSecurityPolicy copyWithZone:zone];
config.enableReachability = _enableReachability;
config.defaultSecurityPolicy = _defaultSecurityPolicy;
}
return config;
}
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkConst.h
================================================
//
// HLNetworkConst.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/22.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#ifndef HLNetworkConst_h
#define HLNetworkConst_h
@protocol HLMultipartFormDataProtocol;
@class HLDebugMessage;
// 网络请求类型
typedef NS_ENUM(NSUInteger, HLRequestTaskType) {
Upload = 16,
Download = 17
};
// 网络请求类型
typedef NS_ENUM(NSUInteger, HLRequestMethodType) {
GET = 10,
POST = 11,
HEAD = 12,
PUT = 13,
PATCH = 14,
DELETE = 15
};
// 请求的序列化格式
typedef NS_ENUM(NSUInteger, HLRequestSerializerType) {
// Content-Type = application/x-www-form-urlencoded
RequestHTTP = 100,
// Content-Type = application/json
RequestJSON = 101,
// Content-Type = application/x-plist
RequestPlist = 102
};
// 请求返回的序列化格式
typedef NS_ENUM(NSUInteger, HLResponseSerializerType) {
// 默认的Response序列化方式(不处理)
ResponseHTTP = 200,
// 使用NSJSONSerialization解析Response Data
ResponseJSON = 201,
// 使用NSPropertyListSerialization解析Response Data
ResponsePlist = 202,
// 使用NSXMLParser解析Response Data
ResponseXML = 203
};
// reachability的状态
typedef NS_ENUM(NSUInteger, HLReachabilityStatus) {
HLReachabilityStatusUnknown,
HLReachabilityStatusNotReachable,
HLReachabilityStatusReachableViaWWAN,
HLReachabilityStatusReachableViaWiFi
};
// 定义的Block
// 请求结果回调
typedef void(^HLSuccessBlock)(id __nullable responseObj);
// 请求失败回调
typedef void(^HLFailureBlock)(NSError * __nullable error);
// 请求进度回调
typedef void(^HLProgressBlock)(NSProgress * __nullable progress);
// formData拼接回调
typedef void(^HLRequestConstructingBodyBlock)(id<HLMultipartFormDataProtocol> __nullable formData);
// debug回调
typedef void(^HLDebugBlock)(HLDebugMessage * __nonnull debugMessage);
// reachability回调
typedef void(^HLReachabilityBlock)(HLReachabilityStatus status);
// 桥接回调
typedef void(^HLCallbackBlock)(id __nonnull request, id __nullable responseObject, NSError * __nullable error);
#endif /* HLNetworkConst_h */
================================================
FILE: HLNetworking/Source/Config/HLNetworkMacro.h
================================================
//
// HLNetworkMacro.h
// HLNetworking
//
// Created by wangshiyu13 on 24/11/2016.
// Copyright © 2016 wangshiyu13. All rights reserved.
//
#ifndef HLNetworkMacro_h
#define HLNetworkMacro_h
static inline BOOL IsEmptyValue(id thing) {
return thing == nil
|| ([thing respondsToSelector:@selector(length)]
&& [(NSData *)thing length] == 0)
|| ([thing respondsToSelector:@selector(count)]
&& [(NSArray *)thing count] == 0)
|| ([thing isKindOfClass:[NSNull class]]);
}
#if DEBUG
#define HLNetLog(...) NSLog(__VA_ARGS__)
#else
#define HLNetLog(...) {}
#endif
#define HL_SAFE_BLOCK(BlockName, ...) ({ !BlockName ? nil : BlockName(__VA_ARGS__); })
#define HLLock() dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER)
#define HLUnlock() dispatch_semaphore_signal(self->_lock)
#pragma mark - weakify strongify
#if DEBUG
#define hl_keywordify autoreleasepool {}
#else
#define hl_keywordify try {} @catch (...) {}
#endif
#define hl_weakify_(INDEX, CONTEXT, VAR) \
CONTEXT __typeof__(VAR) hl_metamacro_concat(VAR, _weak_) = (VAR);
#define hl_strongify_(INDEX, VAR) \
__strong __typeof__(VAR) VAR = hl_metamacro_concat(VAR, _weak_);
#define hl_weakify(...) \
hl_keywordify \
hl_metamacro_foreach_cxt(hl_weakify_,, __weak, __VA_ARGS__)
#define hl_strongify(...) \
hl_keywordify \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
hl_metamacro_foreach(hl_strongify_,, __VA_ARGS__) \
_Pragma("clang diagnostic pop")
/**
* Executes one or more expressions (which may have a void type, such as a call
* to a function that returns no value) and always returns true.
*/
#define hl_metamacro_exprify(...) \
((__VA_ARGS__), true)
/**
* Returns a string representation of VALUE after full macro expansion.
*/
#define hl_metamacro_stringify(VALUE) \
hl_metamacro_stringify_(VALUE)
/**
* Returns A and B concatenated after full macro expansion.
*/
#define hl_metamacro_concat(A, B) \
hl_metamacro_concat_(A, B)
/**
* Returns the Nth variadic argument (starting from zero). At least
* N + 1 variadic arguments must be given. N must be between zero and twenty,
* inclusive.
*/
#define hl_metamacro_at(N, ...) \
hl_metamacro_concat(hl_metamacro_at, N)(__VA_ARGS__)
/**
* Returns the number of arguments (up to twenty) provided to the macro. At
* least one argument must be provided.
*
* Inspired by P99: http://p99.gforge.inria.fr
*/
#define hl_metamacro_argcount(...) \
hl_metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
/**
* Identical to #hl_metamacro_foreach_cxt, except that no CONTEXT argument is
* given. Only the index and current argument will thus be passed to MACRO.
*/
#define hl_metamacro_foreach(MACRO, SEP, ...) \
hl_metamacro_foreach_cxt(hl_metamacro_foreach_iter, SEP, MACRO, __VA_ARGS__)
/**
* For each consecutive variadic argument (up to twenty), MACRO is passed the
* zero-based index of the current argument, CONTEXT, and then the argument
* itself. The results of adjoining invocations of MACRO are then separated by
* SEP.
*
* Inspired by P99: http://p99.gforge.inria.fr
*/
#define hl_metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
hl_metamacro_concat(hl_metamacro_foreach_cxt, hl_metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
/**
* Identical to #hl_metamacro_foreach_cxt. This can be used when the former would
* fail due to recursive macro expansion.
*/
#define hl_metamacro_foreach_cxt_recursive(MACRO, SEP, CONTEXT, ...) \
hl_metamacro_concat(hl_metamacro_foreach_cxt_recursive, hl_metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
/**
* In consecutive order, appends each variadic argument (up to twenty) onto
* BASE. The resulting concatenations are then separated by SEP.
*
* This is primarily useful to manipulate a list of macro invocations into instead
* invoking a different, possibly related macro.
*/
#define hl_hl_metamacro_foreach_concat(BASE, SEP, ...) \
hl_metamacro_foreach_cxt(hl_metamacro_foreach_concat_iter, SEP, BASE, __VA_ARGS__)
/**
* Iterates COUNT times, each time invoking MACRO with the current index
* (starting at zero) and CONTEXT. The results of adjoining invocations of MACRO
* are then separated by SEP.
*
* COUNT must be an integer between zero and twenty, inclusive.
*/
#define hl_metamacro_for_cxt(COUNT, MACRO, SEP, CONTEXT) \
hl_metamacro_concat(hl_metamacro_for_cxt, COUNT)(MACRO, SEP, CONTEXT)
/**
* Returns the first argument given. At least one argument must be provided.
*
* This is useful when implementing a variadic macro, where you may have only
* one variadic argument, but no way to retrieve it (for example, because \c ...
* always needs to match at least one argument).
*
* @code
#define varmacro(...) \
hl_metamacro_head(__VA_ARGS__)
* @endcode
*/
#define hl_metamacro_head(...) \
hl_metamacro_head_(__VA_ARGS__, 0)
/**
* Returns every argument except the first. At least two arguments must be
* provided.
*/
#define hl_metamacro_tail(...) \
hl_metamacro_tail_(__VA_ARGS__)
/**
* Returns the first N (up to twenty) variadic arguments as a new argument list.
* At least N variadic arguments must be provided.
*/
#define hl_metamacro_take(N, ...) \
hl_metamacro_concat(hl_metamacro_take, N)(__VA_ARGS__)
/**
* Removes the first N (up to twenty) variadic arguments from the given argument
* list. At least N variadic arguments must be provided.
*/
#define hl_metamacro_drop(N, ...) \
hl_metamacro_concat(hl_metamacro_drop, N)(__VA_ARGS__)
/**
* Decrements VAL, which must be a number between zero and twenty, inclusive.
*
* This is primarily useful when dealing with indexes and counts in
* metaprogramming.
*/
#define hl_metamacro_dec(VAL) \
hl_metamacro_at(VAL, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
/**
* Increments VAL, which must be a number between zero and twenty, inclusive.
*
* This is primarily useful when dealing with indexes and counts in
* metaprogramming.
*/
#define hl_metamacro_inc(VAL) \
hl_metamacro_at(VAL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
/**
* If A is equal to B, the next argument list is expanded; otherwise, the
* argument list after that is expanded. A and B must be numbers between zero
* and twenty, inclusive. Additionally, B must be greater than or equal to A.
*
* @code
// expands to true
hl_metamacro_if_eq(0, 0)(true)(false)
// expands to false
hl_metamacro_if_eq(0, 1)(true)(false)
* @endcode
*
* This is primarily useful when dealing with indexes and counts in
* metaprogramming.
*/
#define hl_metamacro_if_eq(A, B) \
hl_metamacro_concat(hl_metamacro_if_eq, A)(B)
/**
* Identical to #hl_metamacro_if_eq. This can be used when the former would fail
* due to recursive macro expansion.
*/
#define hl_metamacro_if_eq_recursive(A, B) \
hl_metamacro_concat(hl_metamacro_if_eq_recursive, A)(B)
/**
* Returns 1 if N is an even number, or 0 otherwise. N must be between zero and
* twenty, inclusive.
*
* For the purposes of this test, zero is considered even.
*/
#define hl_metamacro_is_even(N) \
hl_metamacro_at(N, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
/**
* Returns the logical NOT of B, which must be the number zero or one.
*/
#define hl_metamacro_not(B) \
hl_metamacro_at(B, 1, 0)
// IMPLEMENTATION DETAILS FOLLOW!
// Do not write code that depends on anything below this line.
#define hl_metamacro_stringify_(VALUE) # VALUE
#define hl_metamacro_concat_(A, B) A ## B
#define hl_metamacro_foreach_iter(INDEX, MACRO, ARG) MACRO(INDEX, ARG)
#define hl_metamacro_head_(FIRST, ...) FIRST
#define hl_metamacro_tail_(FIRST, ...) __VA_ARGS__
#define hl_metamacro_consume_(...)
#define hl_metamacro_expand_(...) __VA_ARGS__
// implemented from scratch so that hl_metamacro_concat() doesn't end up nesting
#define hl_metamacro_foreach_concat_iter(INDEX, BASE, ARG) hl_metamacro_foreach_concat_iter_(BASE, ARG)
#define hl_metamacro_foreach_concat_iter_(BASE, ARG) BASE ## ARG
// hl_metamacro_at expansions
#define hl_metamacro_at0(...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at1(_0, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at2(_0, _1, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at3(_0, _1, _2, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at4(_0, _1, _2, _3, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at5(_0, _1, _2, _3, _4, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at6(_0, _1, _2, _3, _4, _5, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at8(_0, _1, _2, _3, _4, _5, _6, _7, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at9(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) hl_metamacro_head(__VA_ARGS__)
// hl_metamacro_foreach_cxt expansions
#define hl_metamacro_foreach_cxt0(MACRO, SEP, CONTEXT)
#define hl_metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
#define hl_metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
hl_metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) \
SEP \
MACRO(1, CONTEXT, _1)
#define hl_metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
hl_metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
SEP \
MACRO(2, CONTEXT, _2)
#define hl_metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
hl_metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
SEP \
MACRO(3, CONTEXT, _3)
#define hl_metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
hl_metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
SEP \
MACRO(4, CONTEXT, _4)
#define hl_metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
hl_metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
SEP \
MACRO(5, CONTEXT, _5)
#define hl_metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
hl_metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
SEP \
MACRO(6, CONTEXT, _6)
#define hl_metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
hl_metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
SEP \
MACRO(7, CONTEXT, _7)
#define hl_metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
hl_metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
SEP \
MACRO(8, CONTEXT, _8)
#define hl_metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
hl_metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
SEP \
MACRO(9, CONTEXT, _9)
#define hl_metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
hl_metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
SEP \
MACRO(10, CONTEXT, _10)
#define hl_metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
hl_metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
SEP \
MACRO(11, CONTEXT, _11)
#define hl_metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
hl_metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
SEP \
MACRO(12, CONTEXT, _12)
#define hl_metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
hl_metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
SEP \
MACRO(13, CONTEXT, _13)
#define hl_metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
hl_metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
SEP \
MACRO(14, CONTEXT, _14)
#define hl_metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
hl_metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
SEP \
MACRO(15, CONTEXT, _15)
#define hl_metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
hl_metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
SEP \
MACRO(16, CONTEXT, _16)
#define hl_metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
hl_metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
SEP \
MACRO(17, CONTEXT, _17)
#define hl_metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
hl_metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
SEP \
MACRO(18, CONTEXT, _18)
#define hl_metamacro_foreach_cxt20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \
hl_metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
SEP \
MACRO(19, CONTEXT, _19)
// hl_metamacro_foreach_cxt_recursive expansions
#define hl_metamacro_foreach_cxt_recursive0(MACRO, SEP, CONTEXT)
#define hl_metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
#define hl_metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \
hl_metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) \
SEP \
MACRO(1, CONTEXT, _1)
#define hl_metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \
hl_metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \
SEP \
MACRO(2, CONTEXT, _2)
#define hl_metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
hl_metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \
SEP \
MACRO(3, CONTEXT, _3)
#define hl_metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
hl_metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
SEP \
MACRO(4, CONTEXT, _4)
#define hl_metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
hl_metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
SEP \
MACRO(5, CONTEXT, _5)
#define hl_metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
hl_metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
SEP \
MACRO(6, CONTEXT, _6)
#define hl_metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
hl_metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
SEP \
MACRO(7, CONTEXT, _7)
#define hl_metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
hl_metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
SEP \
MACRO(8, CONTEXT, _8)
#define hl_metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
hl_metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
SEP \
MACRO(9, CONTEXT, _9)
#define hl_metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
hl_metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
SEP \
MACRO(10, CONTEXT, _10)
#define hl_metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
hl_metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
SEP \
MACRO(11, CONTEXT, _11)
#define hl_metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
hl_metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
SEP \
MACRO(12, CONTEXT, _12)
#define hl_metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
hl_metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
SEP \
MACRO(13, CONTEXT, _13)
#define hl_metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
hl_metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
SEP \
MACRO(14, CONTEXT, _14)
#define hl_metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
hl_metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
SEP \
MACRO(15, CONTEXT, _15)
#define hl_metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
hl_metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
SEP \
MACRO(16, CONTEXT, _16)
#define hl_metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
hl_metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
SEP \
MACRO(17, CONTEXT, _17)
#define hl_metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
hl_metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
SEP \
MACRO(18, CONTEXT, _18)
#define hl_metamacro_foreach_cxt_recursive20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \
hl_metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
SEP \
MACRO(19, CONTEXT, _19)
// hl_metamacro_for_cxt expansions
#define hl_metamacro_for_cxt0(MACRO, SEP, CONTEXT)
#define hl_metamacro_for_cxt1(MACRO, SEP, CONTEXT) MACRO(0, CONTEXT)
#define hl_metamacro_for_cxt2(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt1(MACRO, SEP, CONTEXT) \
SEP \
MACRO(1, CONTEXT)
#define hl_metamacro_for_cxt3(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt2(MACRO, SEP, CONTEXT) \
SEP \
MACRO(2, CONTEXT)
#define hl_metamacro_for_cxt4(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt3(MACRO, SEP, CONTEXT) \
SEP \
MACRO(3, CONTEXT)
#define hl_metamacro_for_cxt5(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt4(MACRO, SEP, CONTEXT) \
SEP \
MACRO(4, CONTEXT)
#define hl_metamacro_for_cxt6(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt5(MACRO, SEP, CONTEXT) \
SEP \
MACRO(5, CONTEXT)
#define hl_metamacro_for_cxt7(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt6(MACRO, SEP, CONTEXT) \
SEP \
MACRO(6, CONTEXT)
#define hl_metamacro_for_cxt8(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt7(MACRO, SEP, CONTEXT) \
SEP \
MACRO(7, CONTEXT)
#define hl_metamacro_for_cxt9(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt8(MACRO, SEP, CONTEXT) \
SEP \
MACRO(8, CONTEXT)
#define hl_metamacro_for_cxt10(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt9(MACRO, SEP, CONTEXT) \
SEP \
MACRO(9, CONTEXT)
#define hl_metamacro_for_cxt11(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt10(MACRO, SEP, CONTEXT) \
SEP \
MACRO(10, CONTEXT)
#define hl_metamacro_for_cxt12(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt11(MACRO, SEP, CONTEXT) \
SEP \
MACRO(11, CONTEXT)
#define hl_metamacro_for_cxt13(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt12(MACRO, SEP, CONTEXT) \
SEP \
MACRO(12, CONTEXT)
#define hl_metamacro_for_cxt14(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt13(MACRO, SEP, CONTEXT) \
SEP \
MACRO(13, CONTEXT)
#define hl_metamacro_for_cxt15(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt14(MACRO, SEP, CONTEXT) \
SEP \
MACRO(14, CONTEXT)
#define hl_metamacro_for_cxt16(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt15(MACRO, SEP, CONTEXT) \
SEP \
MACRO(15, CONTEXT)
#define hl_metamacro_for_cxt17(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt16(MACRO, SEP, CONTEXT) \
SEP \
MACRO(16, CONTEXT)
#define hl_metamacro_for_cxt18(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt17(MACRO, SEP, CONTEXT) \
SEP \
MACRO(17, CONTEXT)
#define hl_metamacro_for_cxt19(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt18(MACRO, SEP, CONTEXT) \
SEP \
MACRO(18, CONTEXT)
#define hl_metamacro_for_cxt20(MACRO, SEP, CONTEXT) \
hl_metamacro_for_cxt19(MACRO, SEP, CONTEXT) \
SEP \
MACRO(19, CONTEXT)
// hl_metamacro_if_eq expansions
#define hl_metamacro_if_eq0(VALUE) \
hl_metamacro_concat(hl_metamacro_if_eq0_, VALUE)
#define hl_metamacro_if_eq0_0(...) __VA_ARGS__ hl_metamacro_consume_
#define hl_metamacro_if_eq0_1(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_2(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_3(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_4(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_5(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_6(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_7(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_8(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_9(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_10(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_11(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_12(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_13(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_14(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_15(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_16(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_17(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_18(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_19(...) hl_metamacro_expand_
#define hl_metamacro_if_eq0_20(...) hl_metamacro_expand_
#define hl_metamacro_if_eq1(VALUE) hl_metamacro_if_eq0(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq2(VALUE) hl_metamacro_if_eq1(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq3(VALUE) hl_metamacro_if_eq2(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq4(VALUE) hl_metamacro_if_eq3(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq5(VALUE) hl_metamacro_if_eq4(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq6(VALUE) hl_metamacro_if_eq5(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq7(VALUE) hl_metamacro_if_eq6(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq8(VALUE) hl_metamacro_if_eq7(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq9(VALUE) hl_metamacro_if_eq8(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq10(VALUE) hl_metamacro_if_eq9(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq11(VALUE) hl_metamacro_if_eq10(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq12(VALUE) hl_metamacro_if_eq11(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq13(VALUE) hl_metamacro_if_eq12(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq14(VALUE) hl_metamacro_if_eq13(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq15(VALUE) hl_metamacro_if_eq14(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq16(VALUE) hl_metamacro_if_eq15(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq17(VALUE) hl_metamacro_if_eq16(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq18(VALUE) hl_metamacro_if_eq17(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq19(VALUE) hl_metamacro_if_eq18(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq20(VALUE) hl_metamacro_if_eq19(hl_metamacro_dec(VALUE))
// hl_metamacro_if_eq_recursive expansions
#define hl_metamacro_if_eq_recursive0(VALUE) \
hl_metamacro_concat(hl_metamacro_if_eq_recursive0_, VALUE)
#define hl_metamacro_if_eq_recursive0_0(...) __VA_ARGS__ hl_metamacro_consume_
#define hl_metamacro_if_eq_recursive0_1(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_2(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_3(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_4(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_5(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_6(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_7(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_8(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_9(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_10(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_11(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_12(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_13(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_14(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_15(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_16(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_17(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_18(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_19(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive0_20(...) hl_metamacro_expand_
#define hl_metamacro_if_eq_recursive1(VALUE) hl_metamacro_if_eq_recursive0(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive2(VALUE) hl_metamacro_if_eq_recursive1(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive3(VALUE) hl_metamacro_if_eq_recursive2(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive4(VALUE) hl_metamacro_if_eq_recursive3(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive5(VALUE) hl_metamacro_if_eq_recursive4(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive6(VALUE) hl_metamacro_if_eq_recursive5(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive7(VALUE) hl_metamacro_if_eq_recursive6(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive8(VALUE) hl_metamacro_if_eq_recursive7(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive9(VALUE) hl_metamacro_if_eq_recursive8(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive10(VALUE) hl_metamacro_if_eq_recursive9(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive11(VALUE) hl_metamacro_if_eq_recursive10(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive12(VALUE) hl_metamacro_if_eq_recursive11(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive13(VALUE) hl_metamacro_if_eq_recursive12(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive14(VALUE) hl_metamacro_if_eq_recursive13(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive15(VALUE) hl_metamacro_if_eq_recursive14(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive16(VALUE) hl_metamacro_if_eq_recursive15(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive17(VALUE) hl_metamacro_if_eq_recursive16(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive18(VALUE) hl_metamacro_if_eq_recursive17(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive19(VALUE) hl_metamacro_if_eq_recursive18(hl_metamacro_dec(VALUE))
#define hl_metamacro_if_eq_recursive20(VALUE) hl_metamacro_if_eq_recursive19(hl_metamacro_dec(VALUE))
// hl_metamacro_take expansions
#define hl_metamacro_take0(...)
#define hl_metamacro_take1(...) hl_metamacro_head(__VA_ARGS__)
#define hl_metamacro_take2(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take1(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take3(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take2(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take4(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take3(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take5(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take4(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take6(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take5(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take7(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take6(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take8(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take7(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take9(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take8(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take10(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take9(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take11(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take10(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take12(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take11(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take13(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take12(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take14(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take13(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take15(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take14(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take16(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take15(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take17(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take16(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take18(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take17(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take19(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take18(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_take20(...) hl_metamacro_head(__VA_ARGS__), hl_metamacro_take19(hl_metamacro_tail(__VA_ARGS__))
// hl_metamacro_drop expansions
#define hl_metamacro_drop0(...) __VA_ARGS__
#define hl_metamacro_drop1(...) hl_metamacro_tail(__VA_ARGS__)
#define hl_metamacro_drop2(...) hl_metamacro_drop1(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop3(...) hl_metamacro_drop2(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop4(...) hl_metamacro_drop3(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop5(...) hl_metamacro_drop4(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop6(...) hl_metamacro_drop5(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop7(...) hl_metamacro_drop6(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop8(...) hl_metamacro_drop7(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop9(...) hl_metamacro_drop8(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop10(...) hl_metamacro_drop9(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop11(...) hl_metamacro_drop10(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop12(...) hl_metamacro_drop11(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop13(...) hl_metamacro_drop12(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop14(...) hl_metamacro_drop13(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop15(...) hl_metamacro_drop14(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop16(...) hl_metamacro_drop15(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop17(...) hl_metamacro_drop16(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop18(...) hl_metamacro_drop17(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop19(...) hl_metamacro_drop18(hl_metamacro_tail(__VA_ARGS__))
#define hl_metamacro_drop20(...) hl_metamacro_drop19(hl_metamacro_tail(__VA_ARGS__))
#endif
================================================
FILE: HLNetworking/Source/Config/HLNetworkPolicyConfig.h
================================================
//
// HLNetworkPolicyConfig.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface HLNetworkPolicyConfig : NSObject<NSCopying>
// 是否为后台模式所用的GroupID,该选项只对Task有影响
@property (nonatomic, copy) NSString *AppGroup;
// 是否为后台模式,该选项只对Task有影响
@property (nonatomic, assign) BOOL isBackgroundSession;
// 出现网络请求错误时,是否在请求错误的文字后加上{code},默认为YES
@property (nonatomic, assign) BOOL isErrorCodeDisplayEnabled;
// 请求缓存策略,默认为NSURLRequestUseProtocolCachePolicy
@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
// URLCache设置
@property (nonatomic, assign) NSURLCache *URLCache;
// 快速构建config
+ (HLNetworkPolicyConfig *)config;
// 请使用config
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkPolicyConfig.m
================================================
//
// HLNetworkPolicyConfig.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLNetworkPolicyConfig.h"
@implementation HLNetworkPolicyConfig
+ (HLNetworkPolicyConfig *)config {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (self) {
_isBackgroundSession = NO;
_isErrorCodeDisplayEnabled = YES;
_cachePolicy = NSURLRequestUseProtocolCachePolicy;
_URLCache = [NSURLCache sharedURLCache];
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
HLNetworkPolicyConfig *config = [[[self class] alloc] init];
if (config) {
config.isErrorCodeDisplayEnabled = _isErrorCodeDisplayEnabled;
config.isBackgroundSession = _isBackgroundSession;
config.AppGroup = [_AppGroup copyWithZone:zone];
}
return config;
}
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkRequestConfig.h
================================================
//
// HLNetworkRequestConfig.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
// 默认的请求超时时间
#define HL_API_REQUEST_TIME_OUT 15
// 每个host最大连接数
#define MAX_HTTP_CONNECTION_PER_HOST 5
@interface HLNetworkRequestConfig : NSObject<NSCopying>
// API请求的自定义队列
@property (nonatomic, strong, nullable) dispatch_queue_t callbackQueue;
// 默认的parameters,可以在HLAPI中选择是否使用,默认开启
@property (nonatomic, strong, nullable) NSDictionary<NSString *, NSObject *> *defaultParams;
// 默认的header,可以在HLAPI中覆盖
@property (nonatomic, strong, nullable) NSDictionary<NSString *, NSString *> *defaultHeaders;
// 全局的baseURL,HLAPI的baseURL会覆盖该参数
@property (nonatomic, copy, nullable) NSString *baseURL;
// api版本,用于拼接在请求的Path上
// 默认为infoPlist中的CFBundleShortVersionString,格式为v{version}{r},审核版本为r
@property (nonatomic, copy, nullable) NSString *apiVersion;
// 是否为审核版本,作用于apiVersion,存储在NSUserDefaults中,key为isR
@property (nonatomic, assign) BOOL isJudgeVersion;
// UserAgent,request header中的UA,默认为nil
@property (nonatomic, copy, nullable) NSString *userAgent;
// 每个Host的最大连接数,默认为5
@property (nonatomic, assign) NSUInteger maxHttpConnectionPerHost;
// 网络状态不好时自动重试次数,默认为0
@property (nonatomic, assign) NSUInteger retryCount;
// 请求超时时间,默认为15秒
@property (nonatomic, assign) NSTimeInterval requestTimeoutInterval;
// 获取当前版本
- (nonnull NSString *)getCurrentVersion;
// 快速构建config
+ (nonnull HLNetworkRequestConfig *)config;
// 请使用config
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)new NS_UNAVAILABLE;
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkRequestConfig.m
================================================
//
// HLNetworkRequestConfig.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLNetworkRequestConfig.h"
@implementation HLNetworkRequestConfig
+ (HLNetworkRequestConfig *)config {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (self) {
_callbackQueue = nil;
_maxHttpConnectionPerHost = MAX_HTTP_CONNECTION_PER_HOST;
_requestTimeoutInterval = HL_API_REQUEST_TIME_OUT;
_retryCount = 0;
_apiVersion = nil;
_isJudgeVersion = [[NSUserDefaults standardUserDefaults] boolForKey:@"isR"] ? : YES;
}
return self;
}
- (NSString *)getCurrentVersion {
NSString *origin = [[NSBundle mainBundle].infoDictionary[@"CFBundleShortVersionString"] stringByReplacingOccurrencesOfString:@"." withString:@""];
if (self.isJudgeVersion) {
return [NSString stringWithFormat:@"v%@r", origin];
} else {
return [NSString stringWithFormat:@"v%@", origin];
}
}
- (id)copyWithZone:(NSZone *)zone {
HLNetworkRequestConfig *config = [[[self class] alloc] init];
if (config) {
config.defaultHeaders = [_defaultHeaders copyWithZone:zone];
config.defaultParams = [_defaultParams copyWithZone:zone];
config.baseURL = [_baseURL copyWithZone:zone];
config.apiVersion = [_apiVersion copyWithZone:zone];
config.userAgent = [_userAgent copyWithZone:zone];
config.isJudgeVersion = _isJudgeVersion;
config.requestTimeoutInterval = _requestTimeoutInterval;
config.maxHttpConnectionPerHost = _maxHttpConnectionPerHost;
}
return config;
}
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkTipsConfig.h
================================================
//
// HLNetworkTipsConfig.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT NSString * const HLDefaultGeneralErrorString;
FOUNDATION_EXPORT NSString * const HLDefaultFrequentRequestErrorString;
FOUNDATION_EXPORT NSString * const HLDefaultNetworkNotReachableString;
@interface HLNetworkTipsConfig : NSObject<NSCopying>
// 出现网络请求时,为了给用户比较好的用户体验,而使用的错误提示文字,
// 默认为:服务器连接错误,请稍候重试
@property (nonatomic, copy) NSString *generalErrorTypeStr;
// 用户频繁发送同一个请求,使用的错误提示文字
// 默认为:请求发送速度太快, 请稍候重试
@property (nonatomic, copy) NSString *frequentRequestErrorStr;
// 网络请求开始时,会先检测相应网络域名的Reachability,如果不可达,则直接返回该错误文字
// 默认为:网络不可用,请稍后重试
@property (nonatomic, copy) NSString *networkNotReachableErrorStr;
// 网络指示器(状态栏),默认为YES
@property (nonatomic, assign) BOOL isNetworkingActivityIndicatorEnabled;
// 快速构建config
+ (HLNetworkTipsConfig *)config;
// 请使用config
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end
================================================
FILE: HLNetworking/Source/Config/HLNetworkTipsConfig.m
================================================
//
// HLNetworkTipsConfig.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLNetworkTipsConfig.h"
NSString * const HLDefaultGeneralErrorString = @"服务器连接错误,请稍候重试";
NSString * const HLDefaultFrequentRequestErrorString = @"请求发送速度太快, 请稍候重试";
NSString * const HLDefaultNetworkNotReachableString = @"网络不可用,请稍后重试";
@implementation HLNetworkTipsConfig
+ (HLNetworkTipsConfig *)config {
return [[self alloc] init];
}
- (instancetype)init
{
self = [super init];
if (self) {
_generalErrorTypeStr = HLDefaultGeneralErrorString;
_frequentRequestErrorStr = HLDefaultFrequentRequestErrorString;
_networkNotReachableErrorStr = HLDefaultNetworkNotReachableString;
_isNetworkingActivityIndicatorEnabled = YES;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
HLNetworkTipsConfig *config = [[[self class] alloc] init];
if (config) {
config.generalErrorTypeStr = [_generalErrorTypeStr copyWithZone:zone];
config.frequentRequestErrorStr = [_frequentRequestErrorStr copyWithZone:zone];
config.networkNotReachableErrorStr = [_networkNotReachableErrorStr copyWithZone:zone];
config.isNetworkingActivityIndicatorEnabled = _isNetworkingActivityIndicatorEnabled;
}
return config;
}
@end
================================================
FILE: HLNetworking/Source/Config/HLSecurityPolicyConfig.h
================================================
//
// HLSecurityPolicyConfig.h
// HLPPShop
//
// Created by wangshiyu13 on 2016/9/19.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
// SSL Pinning
typedef NS_ENUM(NSUInteger, HLSSLPinningMode) {
// 不校验Pinning证书
HLSSLPinningModeNone,
// 校验Pinning证书中的PublicKey
HLSSLPinningModePublicKey,
// 校验整个Pinning证书
HLSSLPinningModeCertificate
};
@interface HLSecurityPolicyConfig : NSObject<NSCopying>
// SSL Pinning证书的校验模式,默认为 HLSSLPinningModeNone
@property (readonly, nonatomic, assign) HLSSLPinningMode SSLPinningMode;
// 是否允许使用Invalid 证书,默认为 NO
@property (nonatomic, assign) BOOL allowInvalidCertificates;
// 是否校验在证书 CN 字段中的 domain name,默认为 YES
@property (nonatomic, assign) BOOL validatesDomainName;
// cer证书文件路径
@property (nonatomic, copy) NSString *cerFilePath;
/**
创建新的SecurityPolicy
@param pinningMode 证书校验模式
@return 新的SecurityPolicy
*/
+ (instancetype)policyWithPinningMode:(HLSSLPinningMode)pinningMode;
- (NSDictionary *)toDictionary;
@end
================================================
FILE: HLNetworking/Source/Config/HLSecurityPolicyConfig.m
================================================
//
// HLSecurityPolicyConfig.m
// HLPPShop
//
// Created by wangshiyu13 on 2016/9/19.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import "HLSecurityPolicyConfig.h"
@interface HLSecurityPolicyConfig ()
@property (readwrite, nonatomic, assign) HLSSLPinningMode SSLPinningMode;
@end
@implementation HLSecurityPolicyConfig
+ (instancetype)policyWithPinningMode:(HLSSLPinningMode)pinningMode {
HLSecurityPolicyConfig *securityPolicy = [[HLSecurityPolicyConfig alloc] init];
if (securityPolicy) {
securityPolicy.SSLPinningMode = pinningMode;
securityPolicy.allowInvalidCertificates = NO;
securityPolicy.validatesDomainName = YES;
securityPolicy.cerFilePath = nil;
}
return securityPolicy;
}
- (NSString *)description {
NSMutableString *desc = [NSMutableString string];
#if DEBUG
[desc appendString:@"\n\n----HLSecurityPolicyConfig Start----\n"];
[desc appendFormat:@"SSLPinningMode: %@\n", [self getpinningModeString:self.SSLPinningMode]];
[desc appendFormat:@"AllowInvalidCertificates: %@\n", self.allowInvalidCertificates ? @"YES" : @"NO"];
[desc appendFormat:@"ValidatesDomainName: %@\n", self.validatesDomainName ? @"YES" : @"NO"];
[desc appendFormat:@"CerFilePath: %@\n", self.cerFilePath ?: @"未设置"];
[desc appendString:@"------HLSecurityPolicyConfig End------\n"];
#else
desc = [NSMutableString stringWithFormat:@""];
#endif
return desc;
}
- (NSDictionary *)toDictionary {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"SSLPinningMode"] = [self getpinningModeString:self.SSLPinningMode];
dict[@"AllowInvalidCertificates"] = self.allowInvalidCertificates ? @"YES" : @"NO";
dict[@"ValidatesDomainName"] = self.validatesDomainName ? @"YES" : @"NO";
dict[@"CerFilePath"] = self.cerFilePath ?: @"未设置";
return dict;
}
- (NSString *)debugDescription {
return self.description;
}
- (NSString *)getpinningModeString:(HLSSLPinningMode)mode {
switch (mode) {
case HLSSLPinningModeNone:
return @"HLSSLPinningModeNone";
break;
case HLSSLPinningModePublicKey:
return @"HLSSLPinningModePublicKey";
case HLSSLPinningModeCertificate:
return @"HLSSLPinningModeCertificate";
default:
return @"HLSSLPinningModeNone";
break;
}
}
- (id)copyWithZone:(NSZone *)zone {
HLSecurityPolicyConfig *config = [[[self class] alloc] init];
if (config) {
config.SSLPinningMode = _SSLPinningMode;
config.allowInvalidCertificates = _allowInvalidCertificates;
config.validatesDomainName = _validatesDomainName;
config.cerFilePath = [_cerFilePath copyWithZone:zone];
}
return config;
}
@end
================================================
FILE: HLNetworking/Source/Engine/HLNetworkEngine.h
================================================
//
// HLNetworkEngine.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/22.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLNetworkConst.h"
@class HLNetworkConfig;
@class HLURLRequest;
@interface HLNetworkEngine : NSObject
// 请使用sharedEngine
- (_Nonnull instancetype)init NS_UNAVAILABLE;
+ (_Nonnull instancetype)new NS_UNAVAILABLE;
// 单例
+ (_Nonnull instancetype)sharedEngine;
// 发送请求
// requestObject为HLAPI或者HLTask对象
- (void)sendRequest:(__kindof HLURLRequest * _Nonnull)requestObject
andConfig:(HLNetworkConfig * _Nonnull)config
progressBack:(HLProgressBlock _Nullable)progressCallBack
callBack:(HLCallbackBlock _Nullable)callBack;
// 取消请求
- (void)cancelRequestByIdentifier:(NSString * _Nonnull)identifier;
// 如果task不存在则返回NSNull对象
- (__kindof NSURLSessionTask * _Nullable)requestByIdentifier:(NSString * _Nonnull)identifier;
#pragma mark - reachability相关
// 开始监听,domain为需要监听的域名
- (void)listeningWithDomain:(NSString * _Nonnull)domain listeningBlock:(HLReachabilityBlock _Nonnull)listener;
// 停止监听,domain为需要停止的域名
- (void)stopListeningWithDomain:(NSString * _Nonnull)domain;
@end
================================================
FILE: HLNetworking/Source/Engine/HLNetworkEngine.m
================================================
//
// HLNetworkEngine.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/22.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <AFNetworking/AFHTTPSessionManager.h>
#import <AFNetworking/AFNetworkReachabilityManager.h>
#import "HLNetworkEngine.h"
#import "HLNetworkMacro.h"
#import "HLNetworkConst.h"
#import "HLNetworkConfig.h"
#import "HLURLRequest_InternalParams.h"
#import "HLAPIRequest_InternalParams.h"
#import "HLTaskRequest_InternalParams.h"
@interface HLNetworkEngine (){
dispatch_semaphore_t _lock;
}
@property (nonatomic, strong) NSMutableDictionary <NSString *, __kindof AFURLSessionManager *>*sessionManagerCache;
@property (nonatomic, strong) NSMutableDictionary <NSString *, __kindof NSURLSessionTask *>*sessionTasksCache;
@property (nonatomic, strong) NSMutableDictionary <NSNumber *, NSString *>*resumePathCache;
@property (nonatomic, strong) NSMutableDictionary <NSString *, AFNetworkReachabilityManager *> *reachabilities;
@end
@implementation HLNetworkEngine
- (instancetype)init {
self = [super init];
if (self) {
_lock = dispatch_semaphore_create(1);
_reachabilities = [NSMutableDictionary dictionary];
_sessionManagerCache = [NSMutableDictionary dictionary];
_sessionTasksCache = [NSMutableDictionary dictionary];
_resumePathCache = [NSMutableDictionary dictionary];
}
return self;
}
+ (HLNetworkEngine *)sharedEngine {
static HLNetworkEngine *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}
#pragma mark - 获取AFHTTPSessionManager
/**
根据请求对象获取AFSessionManager
@param requestObject 请求对象
@param config 请求参数
@return AFURLSessionManager
*/
- (AFURLSessionManager *)sessionManagerByRequest:(__kindof HLURLRequest *)requestObject andManagerConfig:(HLNetworkConfig *)config {
if (!requestObject) return nil;
/** 拼接baseUrlStr */
NSString *baseUrlStr = [self createBaseURLString:requestObject andConfig:config];
/** 设置AFSecurityPolicy参数 */
AFSecurityPolicy *securityPolicy = [self createSecurityPolicy:requestObject andConfig:config];
/** 如果requestObject为HLTask */
if ([requestObject isKindOfClass:[HLTaskRequest class]]) {
// AFURLSessionManager
return [self createSessionManager:config
andBaseURLString:baseUrlStr
andSecurityPolicy:securityPolicy];
/** 如果requestObject为HLAPI */
} else if ([requestObject isKindOfClass:[HLAPIRequest class]]) {
// AFHTTPSessionManager
return [self createSessionManager:requestObject
andConfig:config
andBaseURLString:baseUrlStr
andSecurityPolicy:securityPolicy];
} else {
return nil;
}
}
#pragma mark - 移除sessionTask
- (void)removeTaskForKey:(NSString *)hashKey {
HLLock();
if ([self.sessionTasksCache objectForKey:hashKey]) {
[self.sessionTasksCache removeObjectForKey:hashKey];
}
HLUnlock();
}
# pragma mark - 发送请求
- (void)sendRequest:(__kindof HLURLRequest *)requestObject
andConfig:(HLNetworkConfig *)config
progressBack:(HLProgressBlock)progressCallBack
callBack:(HLCallbackBlock)callBack
{
/** 容错 */
if (!requestObject) {
[self faultTolerantProcessWithBlock:callBack
andRequestObject:requestObject
andErrorCode:NSURLErrorUnsupportedURL
andErrorDescription:@"请求对象不存在!"];
return;
}
// 如果缓存中已有当前task,则立即使api返回失败回调,错误信息为frequentRequestErrorStr
if ([self.sessionTasksCache objectForKey:[requestObject hashKey]]) {
[self faultTolerantProcessWithBlock:callBack
andRequestObject:requestObject
andErrorCode:NSURLErrorCancelled
andErrorDescription:config.tips.frequentRequestErrorStr];
return;
}
/** 必要参数 */
/** 生成sessionManager */
AFURLSessionManager *sessionManager = [self sessionManagerByRequest:requestObject andManagerConfig:config];
if (!sessionManager) {
[self faultTolerantProcessWithBlock:callBack
andRequestObject:requestObject
andErrorCode:NSURLErrorUnsupportedURL
andErrorDescription:@"SessionManager无法构建!"];
return;
}
/** 生成requestURLString */
NSString *requestURLString;
NSString *host;
// 如果定义了自定义的cURL, 则直接使用
NSURL *cURL = [NSURL URLWithString:[requestObject customURL]];
if (cURL) {
host = [NSString stringWithFormat:@"%@://%@", cURL.scheme, cURL.host];
requestURLString = cURL.absoluteString;
} else {
NSString *tmpBaseURLStr = (NSString *)[requestObject baseURL] ?: config.request.baseURL;
if ([tmpBaseURLStr hasSuffix:@"/"]) {
tmpBaseURLStr = [tmpBaseURLStr substringWithRange:NSMakeRange(0, tmpBaseURLStr.length - 1)];
}
NSURL *tmpBaseURL = [NSURL URLWithString:tmpBaseURLStr];
host = [NSString stringWithFormat:@"%@://%@", tmpBaseURL.scheme, tmpBaseURL.host];
// 使用BaseUrl + apiversion(可选) + path 组成 UrlString
// 如果有apiVersion且类型不是HLTask时,则在requestUrlStr中插入该参数
if (IsEmptyValue(config.request.apiVersion) || [requestObject isKindOfClass:[HLTaskRequest class]]) {
requestURLString = tmpBaseURL.absoluteString;
} else {
requestURLString = [NSString stringWithFormat:@"%@/%@", tmpBaseURL.absoluteString, config.request.apiVersion];
}
if (!IsEmptyValue([requestObject path])) {
requestURLString = [NSString stringWithFormat:@"%@/%@", requestURLString, [requestObject path]];
}
}
if (IsEmptyValue(requestURLString)) {
[self faultTolerantProcessWithBlock:callBack
andRequestObject:requestObject
andErrorCode:NSURLErrorUnsupportedURL
andErrorDescription:@"requestURLString无法构建!"];
return;
}
/** 网络状态不好使自动放弃该此请求 */
// 设置reachbility,监听url为baseURL
SCNetworkReachabilityRef hostReachable = SCNetworkReachabilityCreateWithName(NULL, [host UTF8String]);
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(hostReachable, &flags);
BOOL isReachable = success &&
(flags & kSCNetworkFlagsReachable) &&
!(flags & kSCNetworkFlagsConnectionRequired);
if (hostReachable) {
CFRelease(hostReachable);
}
// 如果无网络,则立即使api响应失败回调,错误信息是networkNotReachableErrorStr
if (!isReachable) {
[self faultTolerantProcessWithBlock:callBack
andRequestObject:requestObject
andErrorCode:NSURLErrorCannotConnectToHost
andErrorDescription:[NSString stringWithFormat:@"%@, %@ 无法访问", config.tips.networkNotReachableErrorStr, host]];
return;
}
// 进度Block
void (^progressBlock)(NSProgress *progress)
= ^(NSProgress *progress) {
if (progress.totalUnitCount <= 0) return;
dispatch_async_main(config.request.callbackQueue, ^{
if (progressCallBack) {
progressCallBack(progress);
}
if (requestObject.progressHandler) {
requestObject.progressHandler(progress);
}
});
};
/** 根据requestObject类型,发送请求 */
// requestObject为HLAPI时
if ([requestObject isKindOfClass:[HLAPIRequest class]]) {
HLAPIRequest *api = requestObject;
AFHTTPSessionManager *session = (AFHTTPSessionManager *)sessionManager;
/** 生成请求参数 */
NSMutableDictionary<NSString *, id> *requestParams;
requestParams = [NSMutableDictionary dictionaryWithDictionary:api.parameters];
if (config.request.defaultParams && api.useDefaultParams) {
[requestParams addEntriesFromDictionary:config.request.defaultParams];
}
/** 生成需要的Block */
// task成功Block
@hl_weakify(self)
void (^successBlock)(NSURLSessionDataTask *task, id responseObject)
= ^(NSURLSessionDataTask * task, id resultObject) {
// 移除dataTask缓存
@hl_strongify(self)
if (callBack) {
callBack(api, resultObject, nil);
}
[self removeTaskForKey:api.hashKey];
};
// task失败Block
void (^failureBlock)(NSURLSessionDataTask * task, NSError * error)
= ^(NSURLSessionDataTask * task, NSError * error) {
// 移除dataTask缓存
@hl_strongify(self)
if (callBack) {
callBack(api, nil, error);
}
[self removeTaskForKey:api.hashKey];
};
// 执行AFN的请求
NSURLSessionDataTask *dataTask;
switch (api.requestMethodType) {
case GET: {
dataTask =
[session GET:requestURLString
parameters:requestParams
progress:progressBlock
success:successBlock
failure:failureBlock];
}
break;
case DELETE: {
dataTask =
[session DELETE:requestURLString
parameters:requestParams
success:successBlock
failure:failureBlock];
}
break;
case PATCH: {
dataTask =
[session PATCH:requestURLString
parameters:requestParams
success:successBlock
failure:failureBlock];
}
break;
case PUT: {
dataTask =
[session PUT:requestURLString
parameters:requestParams
success:successBlock
failure:failureBlock];
}
break;
case HEAD: {
dataTask =
[session HEAD:requestURLString
parameters:requestParams
success:^(NSURLSessionDataTask * _Nonnull task) {
if (successBlock) {
dispatch_async_main(config.request.callbackQueue, ^{
successBlock(task, nil);
});
}
}
failure:failureBlock];
}
break;
case POST: {
if (![api requestConstructingBodyBlock]) {
dataTask =
[session POST:requestURLString
parameters:requestParams
progress:progressBlock
success:successBlock
failure:failureBlock];
} else {
void (^formDataBlock)(id <AFMultipartFormData> formData)
= ^(id <AFMultipartFormData> formData) {
api.requestConstructingBodyBlock((id<HLMultipartFormDataProtocol>)formData);
};
dataTask = [session POST:requestURLString
parameters:requestParams
constructingBodyWithBlock:formDataBlock
progress:progressBlock
success:successBlock
failure:failureBlock];
}
}
break;
default: {
dataTask =
[session GET:requestURLString
parameters:requestParams
progress:progressBlock
success:successBlock
failure:failureBlock];
}
break;
}
// 缓存dataTask
if (dataTask) {
HLLock();
self.sessionTasksCache[api.hashKey] = dataTask;
HLUnlock();
}
// requestObject为HLTask时
} else if ([requestObject isKindOfClass:[HLTaskRequest class]]) {
/** 准备请求参数 */
HLTaskRequest *task = requestObject;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestURLString]];
NSURL *fileURL = task.filePath ? [NSURL fileURLWithPath:task.filePath] : nil;
if (!fileURL) {
return;
}
/** 生成需要的Block */
// 下载地址Block
NSURL * (^destinationBlock)(NSURL *targetPath, NSURLResponse *response)
= ^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
return fileURL ?: [NSURL fileURLWithPath:path];
};
@hl_weakify(self);
// 上传完成的Block
void (^uploadCompleteBlock)(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error)
= ^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
@hl_strongify(self);
if (callBack) {
callBack(task, responseObject, error);
}
[self removeTaskForKey:task.hashKey];
};
// 下载完成的Block
void (^donwloadCompleteBlcok)(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error)
= ^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
@hl_strongify(self);
if (callBack) {
callBack(task, filePath, error);
}
[self removeTaskForKey:task.hashKey];
};
NSURLSessionTask *sessionTask;
switch (task.requestTaskType) {
case Upload: {
[request setHTTPMethod:@"POST"];
sessionTask = [sessionManager uploadTaskWithRequest:request
fromFile:fileURL
progress:progressBlock
completionHandler:uploadCompleteBlock];
}
break;
case Download: {
NSData *data = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:task.resumePath]];
if (data) {
sessionTask = [sessionManager downloadTaskWithResumeData:data
progress:progressBlock
destination:destinationBlock
completionHandler:donwloadCompleteBlcok];
} else {
sessionTask = [sessionManager downloadTaskWithRequest:request
progress:progressBlock
destination:destinationBlock
completionHandler:donwloadCompleteBlcok];
}
HLLock();
self.resumePathCache[@(sessionTask.hash)] = task.resumePath;
HLUnlock();
}
break;
default: break;
}
// 缓存dataTask
if (sessionTask) {
[sessionTask resume];
HLLock();
self.sessionTasksCache[task.hashKey] = sessionTask;
HLUnlock();
}
} else {
return;
}
}
- (void)cancelRequestByIdentifier:(NSString *)identifier {
NSURLSessionTask *sessionTask = [self.sessionTasksCache objectForKey:identifier];
if (sessionTask) {
HLLock();
if ([sessionTask isKindOfClass:[NSURLSessionDownloadTask class]]) {
NSURLSessionDownloadTask * downloadTask = (NSURLSessionDownloadTask *)sessionTask;
[downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
[resumeData writeToFile:self.resumePathCache[@(downloadTask.hash)] atomically:YES];
}];
} else {
[sessionTask cancel];
[self.sessionTasksCache removeObjectForKey:identifier];
}
HLUnlock();
}
}
- (__kindof NSURLSessionTask *)requestByIdentifier:(NSString *)identifier {
return [self.sessionTasksCache objectForKey:identifier] ?: nil;
}
- (void)listeningWithDomain:(NSString *)domain listeningBlock:(HLReachabilityBlock)listener {
AFNetworkReachabilityManager *manager = [self.reachabilities objectForKey:domain];
if (!manager) {
manager = [AFNetworkReachabilityManager managerForDomain:domain];
self.reachabilities[domain] = manager;
}
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
HLReachabilityStatus result = HLReachabilityStatusUnknown;
switch (status) {
case AFNetworkReachabilityStatusUnknown:
result = HLReachabilityStatusUnknown;
break;
case AFNetworkReachabilityStatusNotReachable:
result = HLReachabilityStatusNotReachable;
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
result = HLReachabilityStatusReachableViaWWAN;
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
result = HLReachabilityStatusReachableViaWiFi;
break;
default:
result = HLReachabilityStatusUnknown;
break;
}
if (listener) {
listener(result);
}
}];
[manager startMonitoring];
}
- (void)stopListeningWithDomain:(NSString *)domain {
AFNetworkReachabilityManager *manager = [self.reachabilities objectForKey:domain];
if (manager) {
[manager stopMonitoring];
if ([self.reachabilities objectForKey:domain]) {
[self.reachabilities removeObjectForKey:domain];
}
}
}
#pragma mark - private method
// 创建BaseURLString
- (NSString *)createBaseURLString:(HLURLRequest *)requestObject andConfig:(HLNetworkConfig *)config {
NSString *baseUrlStr;
// 如果定义了自定义的cURL, 则直接使用
NSURL *cURL = [NSURL URLWithString:requestObject.customURL];
if (cURL.host) {
baseUrlStr = [NSString stringWithFormat:@"%@://%@", cURL.scheme ?: @"https", cURL.host];
} else {
NSAssert(requestObject.baseURL != nil || config.request.baseURL != nil,
@"api baseURL 和 self.config.baseurl 两者必须有一个有值");
NSString *tmpStr = requestObject.baseURL ?: config.request.baseURL;
// 在某些情况下,一些用户会直接把整个url地址写进 baseUrl
// 因此,还需要对baseUrl 进行一次切割
NSURL *tmpURL = [NSURL URLWithString:tmpStr];
baseUrlStr = [NSString stringWithFormat:@"%@://%@", tmpURL.scheme ?: @"https", tmpURL.host];;
}
return baseUrlStr;
}
// 创建AFSecurityPolicy
- (AFSecurityPolicy *)createSecurityPolicy:(HLURLRequest *)requestObject andConfig:(HLNetworkConfig *)config {
HLSecurityPolicyConfig *requestSecurityPolicy = requestObject.securityPolicy;
NSUInteger pinningMode = requestSecurityPolicy.SSLPinningMode ?: config.defaultSecurityPolicy.SSLPinningMode;
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:pinningMode];
securityPolicy.allowInvalidCertificates = requestSecurityPolicy.allowInvalidCertificates ?: config.defaultSecurityPolicy.allowInvalidCertificates;
securityPolicy.validatesDomainName = requestSecurityPolicy.validatesDomainName ?: config.defaultSecurityPolicy.validatesDomainName;
NSString *cerPath = requestSecurityPolicy.cerFilePath ?: config.defaultSecurityPolicy.cerFilePath;
NSData *certData = nil;
if (cerPath && ![cerPath isEqualToString:@""]) {
certData = [NSData dataWithContentsOfFile:cerPath];
if (certData) {
securityPolicy.pinnedCertificates = [NSSet setWithObject:certData];
}
}
return securityPolicy;
}
- (AFURLSessionManager *)createSessionManager:(HLNetworkConfig *)config
andBaseURLString:(NSString *)baseUrlStr
andSecurityPolicy:(AFSecurityPolicy *)securityPolicy {
AFURLSessionManager *sessionManager = [self.sessionManagerCache objectForKey:baseUrlStr];
// 如果缓存中取不到对应的sessionManager,则创建一个新的SessionManager
if (!sessionManager) {
NSURLSessionConfiguration *sessionConfig;
if (config) {
if (config.policy.isBackgroundSession) {
NSString *kBackgroundSessionID = [NSString stringWithFormat:@"com.wangshiyu13.backgroundSession.task.%@", baseUrlStr];
NSString *kSharedContainerIdentifier = config.policy.AppGroup ?: [NSString stringWithFormat:@"com.wangshiyu13.testApp"];
sessionConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kBackgroundSessionID];
sessionConfig.sharedContainerIdentifier = kSharedContainerIdentifier;
} else {
sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
}
sessionConfig.HTTPMaximumConnectionsPerHost = config.request.maxHttpConnectionPerHost;
} else {
sessionConfig.HTTPMaximumConnectionsPerHost = MAX_HTTP_CONNECTION_PER_HOST;
}
sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:sessionConfig];
[self.sessionManagerCache setObject:sessionManager forKey:baseUrlStr];
}
sessionManager.securityPolicy = securityPolicy;
return sessionManager;
}
// 创建Request序列化工具
- (AFHTTPRequestSerializer *)createRequestSerializer:(HLAPIRequest *)requestObject
andConfig:(HLNetworkConfig *)config {
AFHTTPRequestSerializer *requestSerializer;
switch ([requestObject requestSerializerType]) {
case RequestHTTP:
requestSerializer = [AFHTTPRequestSerializer serializer];
break;
case RequestJSON:
requestSerializer = [AFJSONRequestSerializer serializer];
break;
case RequestPlist:
requestSerializer = [AFPropertyListRequestSerializer serializer];
break;
default:
requestSerializer = [AFHTTPRequestSerializer serializer];
break;
}
requestSerializer.cachePolicy = [requestObject cachePolicy];
requestSerializer.timeoutInterval = [requestObject timeoutInterval];
NSDictionary *requestHeaderFieldParams = [requestObject header];
if (![[requestHeaderFieldParams allKeys] containsObject:@"User-Agent"] &&
config.request.userAgent) {
[requestSerializer setValue:config.request.userAgent forHTTPHeaderField:@"User-Agent"];
}
if (requestHeaderFieldParams) {
[requestHeaderFieldParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[requestSerializer setValue:obj forHTTPHeaderField:key];
}];
}
return requestSerializer;
}
// 创建Response序列化工具
- (AFHTTPResponseSerializer *)createResponseSerializer:(HLAPIRequest *)requestObject andConfig:(HLNetworkConfig *)config {
AFHTTPResponseSerializer *responseSerializer;
switch ([requestObject responseSerializerType]) {
case ResponseHTTP:
responseSerializer = [AFHTTPResponseSerializer serializer];
break;
case ResponseJSON:
responseSerializer = [AFJSONResponseSerializer serializer];
break;
case ResponsePlist:
responseSerializer = [AFPropertyListResponseSerializer serializer];
break;
case ResponseXML:
responseSerializer = [AFXMLParserResponseSerializer serializer];
break;
default:
responseSerializer = [AFHTTPResponseSerializer serializer];
break;
}
if (requestObject.accpetContentTypes) {
NSMutableSet *tmpSet = [NSMutableSet setWithSet:requestObject.accpetContentTypes];
[tmpSet unionSet:responseSerializer.acceptableContentTypes];
responseSerializer.acceptableContentTypes = [tmpSet copy];
}
return responseSerializer;
}
// 创建AFHTTPSessionManager
- (AFHTTPSessionManager *)createSessionManager:(HLAPIRequest *)requestObject
andConfig:(HLNetworkConfig *)config
andBaseURLString:(NSString *)baseUrlStr
andSecurityPolicy:(AFSecurityPolicy *)securityPolicy
{
AFHTTPSessionManager *sessionManager = [self.sessionManagerCache objectForKey:baseUrlStr];
if (!sessionManager) {
// 根据传入的BaseURL创建新的SessionManager
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPMaximumConnectionsPerHost = config.request.maxHttpConnectionPerHost;
sessionConfig.requestCachePolicy = [requestObject cachePolicy] ?: config.policy.cachePolicy;
sessionConfig.timeoutIntervalForRequest = [requestObject timeoutInterval] ?: config.request.requestTimeoutInterval;
sessionConfig.URLCache = config.policy.URLCache;
sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:baseUrlStr] sessionConfiguration:sessionConfig];
[self.sessionManagerCache setObject:sessionManager forKey:baseUrlStr];
}
sessionManager.requestSerializer = [self createRequestSerializer:requestObject andConfig:config];
sessionManager.responseSerializer = [self createResponseSerializer:requestObject andConfig:config];
sessionManager.securityPolicy = securityPolicy;
return sessionManager;
}
// 容错处理
- (void)faultTolerantProcessWithBlock:(HLCallbackBlock)callbackBlock
andRequestObject:(__kindof HLURLRequest *)requestObject
andErrorCode:(NSInteger)errorCode
andErrorDescription:(NSString *)errorDescription {
NSError *error = [NSError errorWithDomain:NSURLErrorDomain
code:NSURLErrorUnsupportedURL
userInfo:@{NSLocalizedDescriptionKey: errorDescription}];
if (callbackBlock) {
callbackBlock(requestObject, nil, error);
}
}
@end
================================================
FILE: HLNetworking/Source/Generator/Request/API/HLAPIRequest.h
================================================
//
// HLAPIRequest.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLRequest.h"
#import "HLFormDataConfig.h"
@class HLAPIRequest;
NS_ASSUME_NONNULL_BEGIN
#pragma mark - 用于转换回调结果的代理
@protocol HLReformerDelegate <NSObject>
@required
/**
一般用来进行JSON -> Model 数据的转换工作。返回的id,如果没有error,则为转换成功后的Model数据。如果有error, 则直接返回传参中的responseObject
@param request 调用的request
@param responseObject 请求的返回
@param error 请求的错误
@return 整理过后的请求数据
*/
- (nullable id)reformerObject:(id)responseObject andError:(NSError * _Nullable)error atRequest:(HLAPIRequest *)request;
@end
@interface HLAPIRequest : HLURLRequest
#pragma mark - property
@property (nonatomic, assign, readonly) BOOL useDefaultParams;
@property (nonatomic, strong, readonly) Class objClz;
@property (nonatomic, copy, readonly) NSDictionary<NSString *, NSObject *> *parameters;
@property (nonatomic, copy, readonly) NSDictionary<NSString *, NSString *> *header;
@property (nonatomic, copy, readonly) NSSet *accpetContentTypes;
#pragma mark - parameters append method
/**
进行JSON -> Model 数据的转换工作的Delegate
如果设置了ReformerDelegate,则使用ReformerDelegate的obj解析,否则直接返回
提供该Delegate主要用于Reformer的不相关代码的解耦工作
param responseObject 请求回调对象
param error 错误信息
@return 请求结果数据
*/
- (HLAPIRequest *(^)(id<HLReformerDelegate> _Nullable delegate))setObjReformerDelegate;
// HTTP 请求的返回可接受的内容类型,默认为nil,该参数会覆盖HLResponseSerializerType
- (HLAPIRequest *(^)(NSSet * _Nullable contentTypes))setAccpetContentTypes;
// 是否使用APIManager.config的默认参数,默认为YES
- (HLAPIRequest *(^)(BOOL enable))enableDefaultParams;
// 设置HLAPI对应的返回值模型类型
- (HLAPIRequest *(^)(NSString *clzName))setResponseClass;
// 请求方法 GET POST等
- (HLAPIRequest *(^)(HLRequestMethodType requestMethodType))setMethod;
// Request 序列化类型:JSON, HTTP, 见HLRequestSerializerType
- (HLAPIRequest *(^)(HLRequestSerializerType requestSerializerType))setRequestType;
// Response 序列化类型: JSON, HTTP
- (HLAPIRequest *(^)(HLResponseSerializerType responseSerializerType))setResponseType;
// 请求中的参数,每次设置都会覆盖之前的内容
- (HLAPIRequest *(^)(NSDictionary<NSString *, id> * _Nullable parameters))setParams;
// 请求中的参数,每次设置都是添加新参数,不会覆盖之前的内容
- (HLAPIRequest *(^)(NSDictionary<NSString *, id> * _Nullable parameters))addParams;
// HTTP 请求的头部区域自定义,默认为nil
- (HLAPIRequest *(^)(NSDictionary<NSString *, NSString *> * _Nullable header))setHeader;
#pragma mark - process
// 开启API 请求
- (HLAPIRequest *)start;
// 取消API 请求
- (HLAPIRequest *)cancel;
#pragma mark - handler block function
/**
用于组织POST体的formData
*/
- (HLAPIRequest *(^)(HLRequestConstructingBodyBlock))formData;
#pragma mark - 重写父类方法,用于转换类型
// 设置HLAPI的requestDelegate
- (HLAPIRequest *(^)(id<HLURLRequestDelegate> delegate))setDelegate;
// 设置API的baseURL,该参数会覆盖config中的baseURL
- (HLAPIRequest *(^)(NSString *baseURL))setBaseURL;
// urlQuery,baseURL后的地址
- (HLAPIRequest *(^)(NSString * _Nullable path))setPath;
// 自定义的RequestUrl,该参数会无视任何baseURL的设置,优先级最高
- (HLAPIRequest *(^)(NSString *customURL))setCustomURL;
// HTTPS 请求的Security策略
- (HLAPIRequest *(^)(HLSecurityPolicyConfig *securityPolicy))setSecurityPolicy;
// HTTP 请求的Cache策略
- (HLAPIRequest *(^)(NSURLRequestCachePolicy requestCachePolicy))setCachePolicy;
// HTTP 请求超时的时间,默认为15秒
- (HLAPIRequest *(^)(NSTimeInterval requestTimeoutInterval))setTimeout;
/**
API完成后的成功回调
写法:
.success(^(id obj) {
dosomething
})
*/
- (HLAPIRequest *(^)(HLSuccessBlock))success;
/**
API完成后的失败回调
写法:
.failure(^(NSError *error) {
})
*/
- (HLAPIRequest *(^)(HLFailureBlock))failure;
/**
API上传、下载等长时间执行的Progress进度
写法:
.progress(^(NSProgress *proc){
NSLog(@"当前进度:%@", proc);
})
*/
- (HLAPIRequest *(^)(HLProgressBlock))progress;
/**
用于Debug的Block
block内返回HLDebugMessage对象
*/
- (HLAPIRequest *(^)(HLDebugBlock))debug;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Generator/Request/API/HLAPIRequest.m
================================================
//
// HLAPIRequest.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLRequest_InternalParams.h"
#import "HLAPIRequest_InternalParams.h"
#import "HLNetworkManager.h"
#import "HLNetworkConfig.h"
#import "HLSecurityPolicyConfig.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-implementation"
@implementation HLAPIRequest
#pragma mark - initialize method
- (instancetype)init {
self = [super init];
if (self) {
_useDefaultParams = YES;
_objClz = [NSObject class];
_accpetContentTypes = nil;
_header = [HLNetworkManager config].request.defaultHeaders;
_parameters = nil;
_requestMethodType = GET;
_requestSerializerType = RequestHTTP;
_responseSerializerType = ResponseJSON;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
HLAPIRequest *request = [super copyWithZone:zone];
if (request) {
request.useDefaultParams = _useDefaultParams;
request.objClz = _objClz;
request.accpetContentTypes = [_accpetContentTypes copyWithZone:zone];
request.header = [_header copyWithZone:zone];
request.parameters = [_parameters copyWithZone:zone];
request.requestMethodType = _requestMethodType;
request.requestSerializerType = _requestSerializerType;
request.responseSerializerType = _responseSerializerType;
request.objReformerDelegate = _objReformerDelegate;
}
return request;
}
#pragma mark - parameters append method
/**
进行JSON -> Model 数据的转换工作的Delegate
如果设置了ReformerDelegate,则使用ReformerDelegate的obj解析,否则直接返回
提供该Delegate主要用于Reformer的不相关代码的解耦工作
param responseObject 请求回调对象
param error 错误信息
@return 请求结果数据
*/
- (HLAPIRequest *(^)(id<HLReformerDelegate> delegate))setObjReformerDelegate {
return ^HLAPIRequest* (id<HLReformerDelegate> delegate) {
self.objReformerDelegate = delegate;
return self;
};
}
/**
HTTP 请求的返回可接受的内容类型
默认为:[NSSet setWithObjects:
@"text/json",
@"text/html",
@"application/json",
@"text/javascript", nil];
*/
- (HLAPIRequest *(^)(NSSet *contentTypes))setAccpetContentTypes {
return ^HLAPIRequest* (NSSet *contentTypes) {
self.accpetContentTypes = contentTypes;
return self;
};
}
// 是否使用APIManager.config的默认参数
- (HLAPIRequest *(^)(BOOL enable))enableDefaultParams {
return ^HLAPIRequest* (BOOL enable) {
self.useDefaultParams = enable;
return self;
};
}
// 设置HLAPI对应的返回值模型类型
- (HLAPIRequest *(^)(NSString *clzName))setResponseClass {
return ^HLAPIRequest* (NSString *clzName) {
Class clz = NSClassFromString(clzName);
if (clz) {
self.objClz = clz;
} else {
self.objClz = nil;
}
return self;
};
}
// 请求方法 GET POST等
- (HLAPIRequest *(^)(HLRequestMethodType requestMethodType))setMethod {
return ^HLAPIRequest* (HLRequestMethodType requestMethodType) {
self.requestMethodType = requestMethodType;
return self;
};
}
// Request 序列化类型:JSON, HTTP, 见HLRequestSerializerType
- (HLAPIRequest *(^)(HLRequestSerializerType requestSerializerType))setRequestType {
return ^HLAPIRequest* (HLRequestSerializerType requestSerializerType) {
self.requestSerializerType = requestSerializerType;
return self;
};
}
// Response 序列化类型: JSON, HTTP
- (HLAPIRequest *(^)(HLResponseSerializerType responseSerializerType))setResponseType {
return ^HLAPIRequest* (HLResponseSerializerType responseSerializerType) {
self.responseSerializerType = responseSerializerType;
return self;
};
}
// 请求中的参数,每次设置都会覆盖之前的内容
- (HLAPIRequest *(^)(NSDictionary<NSString *, id> *parameters))setParams {
return ^HLAPIRequest* (NSDictionary<NSString *, id> *parameters) {
self.parameters = parameters;
return self;
};
}
// 请求中的参数,每次设置都是添加新参数,不会覆盖之前的内容
- (HLAPIRequest *(^)(NSDictionary<NSString *, id> *parameters))addParams {
return ^HLAPIRequest* (NSDictionary<NSString *, id> *parameters) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:self.parameters];
[dict addEntriesFromDictionary:parameters];
self.parameters = [dict copy];
return self;
};
}
// HTTP 请求的头部区域自定义,默认为nil
- (HLAPIRequest *(^)(NSDictionary<NSString *, NSString *> *header))setHeader {
return ^HLAPIRequest* (NSDictionary<NSString *, NSString *> *header) {
self.header = header;
return self;
};
}
#pragma mark - handler block function
- (HLAPIRequest *(^)(HLRequestConstructingBodyBlock))formData {
return ^HLAPIRequest* (HLRequestConstructingBodyBlock bodyBlock) {
self.requestConstructingBodyBlock = bodyBlock;
return self;
};
}
#pragma mark - helper
- (NSUInteger)hash {
NSString *hashStr = nil;
if (self.customURL) {
hashStr = [NSString stringWithFormat:@"%@%@?%@?%lu",
self.header,
self.customURL,
self.parameters,
(unsigned long)self.requestMethodType];
} else {
hashStr = [NSString stringWithFormat:@"%@%@/%@?%@?%lu",
self.header,
self.baseURL,
self.path,
self.parameters,
(unsigned long)self.requestMethodType];
}
return [hashStr hash];
}
// 拼接打印信息
- (NSString *)description {
NSMutableString *desc = [NSMutableString string];
#if DEBUG
[desc appendString:@"\n===============HLAPI Start===============\n"];
[desc appendFormat:@"APIVersion: %@\n", [HLNetworkManager config].request.apiVersion ?: @"未设置"];
[desc appendFormat:@"Class: %@\n", self.objClz];
[desc appendFormat:@"BaseURL: %@\n", self.baseURL ?: [HLNetworkManager config].request.baseURL];
[desc appendFormat:@"Path: %@\n", self.path ?: @"未设置"];
[desc appendFormat:@"CustomURL: %@\n", self.customURL ?: @"未设置"];
[desc appendFormat:@"Parameters: %@\n", self.parameters ?: @"未设置"];
[desc appendFormat:@"Header: %@\n", self.header ?: @"未设置"];
[desc appendFormat:@"ContentTypes: %@\n", self.accpetContentTypes];
[desc appendFormat:@"TimeoutInterval: %f\n", self.timeoutInterval];
[desc appendFormat:@"SecurityPolicy: %@\n", self.securityPolicy];
[desc appendFormat:@"RequestMethodType: %@\n", [self getRequestMethodString:self.requestMethodType]];
[desc appendFormat:@"RequestSerializerType: %@\n", [self getRequestSerializerTypeString: self.requestSerializerType]];
[desc appendFormat:@"ResponseSerializerType: %@\n", [self getResponseSerializerTypeString: self.responseSerializerType]];
[desc appendFormat:@"CachePolicy: %@\n", [self getCachePolicy:self.cachePolicy]];
[desc appendString:@"=================HLAPI End================\n"];
#else
desc = [NSMutableString stringWithFormat:@""];
#endif
return desc;
}
- (NSString *)debugDescription {
return self.description;
}
- (NSString *)getCachePolicy:(NSURLRequestCachePolicy)policy {
switch (policy) {
case NSURLRequestUseProtocolCachePolicy:
return @"NSURLRequestUseProtocolCachePolicy";
break;
case NSURLRequestReloadIgnoringLocalCacheData:
return @"NSURLRequestReloadIgnoringLocalCacheData";
break;
case NSURLRequestReloadIgnoringLocalAndRemoteCacheData:
return @"NSURLRequestReloadIgnoringLocalAndRemoteCacheData";
break;
case NSURLRequestReturnCacheDataElseLoad:
return @"NSURLRequestReturnCacheDataElseLoad";
break;
case NSURLRequestReturnCacheDataDontLoad:
return @"NSURLRequestReturnCacheDataDontLoad";
break;
case NSURLRequestReloadRevalidatingCacheData:
return @"NSURLRequestReloadRevalidatingCacheData";
break;
default:
return @"NULL";
break;
}
}
- (NSString *)getRequestMethodString:(HLRequestMethodType)method {
switch (method) {
case GET:
return @"GET";
break;
case POST:
return @"POST";
break;
case HEAD:
return @"HEAD";
break;
case PUT:
return @"PUT";
break;
case PATCH:
return @"PATCH";
break;
case DELETE:
return @"PATCH";
break;
default:
return @"NULL";
break;
}
}
- (NSString *)getRequestSerializerTypeString:(HLRequestSerializerType)type {
switch (type) {
case RequestJSON:
return @"RequestJSON";
break;
case RequestPlist:
return @"RequestPlist";
break;
case RequestHTTP:
return @"RequestHTTP";
break;
default:
return @"NULL";
break;
}
}
- (NSString *)getResponseSerializerTypeString:(HLResponseSerializerType)type {
switch (type) {
case ResponseXML:
return @"ResponseXML";
break;
case ResponsePlist:
return @"ResponsePlist";
break;
case ResponseHTTP:
return @"ResponseHTTP";
break;
case ResponseJSON:
return @"ResponseJSON";
break;
default:
return @"NULL";
break;
}
}
- (NSDictionary *)toDictionary {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"APIVersion"] = [HLNetworkManager config].request.apiVersion ?: @"未设置";
dict[@"Class"] = [NSString stringWithFormat:@"%@", self.objClz];
dict[@"BaseURL"] = self.baseURL ?: [HLNetworkManager config].request.baseURL;
dict[@"Path"] = self.path ?: @"未设置";
dict[@"CustomURL"] = self.customURL ?: @"未设置";
dict[@"Parameters"] = self.parameters ?: @"未设置";
dict[@"Header"] = self.header ?: @"未设置";
dict[@"ContentTypes"] = [NSString stringWithFormat:@"%@", self.accpetContentTypes];
dict[@"TimeoutInterval"] = [NSString stringWithFormat:@"%f", self.timeoutInterval];
dict[@"SecurityPolicy"] = [self.securityPolicy toDictionary];
dict[@"RequestMethodType"] = [self getRequestMethodString:self.requestMethodType];
dict[@"RequestSerializerType"] = [self getRequestSerializerTypeString: self.requestSerializerType];
dict[@"ResponseSerializerType"] = [self getResponseSerializerTypeString: self.responseSerializerType];
dict[@"CachePolicy"] = [self getCachePolicy:self.cachePolicy];
return dict;
}
@end
#pragma clang diagnostic pop
================================================
FILE: HLNetworking/Source/Generator/Request/API/HLAPIRequest_InternalParams.h
================================================
//
// HLAPIRequest_InternalParams.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLAPIRequest.h"
NS_ASSUME_NONNULL_BEGIN
@interface HLAPIRequest ()
// readOnly property
@property (nonatomic, strong, nullable) Class objClz;
@property (nonatomic, assign) BOOL useDefaultParams;
@property (nonatomic, weak, nullable) id<HLReformerDelegate> objReformerDelegate;
@property (nonatomic, assign) HLRequestMethodType requestMethodType;
@property (nonatomic, assign) HLRequestSerializerType requestSerializerType;
@property (nonatomic, assign) HLResponseSerializerType responseSerializerType;
@property (nonatomic, copy, nullable) NSDictionary<NSString *, NSObject *> *parameters;
@property (nonatomic, copy, nullable) NSDictionary<NSString *, NSString *> *header;
@property (nonatomic, copy) NSSet *accpetContentTypes;
@property (nonatomic, copy, nullable) HLRequestConstructingBodyBlock requestConstructingBodyBlock;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Generator/Request/Base/HLURLRequest.h
================================================
//
// HLURLRequest.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLNetworkConst.h"
@class HLURLRequest;
@class HLSecurityPolicyConfig;
@protocol HLMultipartFormDataProtocol;
@protocol HLURLRequestDelegate;
NS_ASSUME_NONNULL_BEGIN
#pragma mark - HLAPIRequestDelegate
@protocol HLURLRequestDelegate <NSObject>
@optional
// 请求将要发出
- (void)requestWillBeSent:(nullable __kindof HLURLRequest *)request;
// 请求已经发出
- (void)requestDidSent:(nullable __kindof HLURLRequest *)request;
@end
@interface HLURLRequest : NSObject<NSCopying>
#pragma mark - property
@property (nonatomic, assign, readonly) NSTimeInterval timeoutInterval;
@property (nonatomic, copy, readonly) NSString *baseURL;
@property (nonatomic, copy, readonly) NSString *path;
@property (nonatomic, copy, nullable, getter=customURL, readonly) NSString *cURL;
#pragma mark - initialize method
// 请使用API
+ (instancetype)request;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
#pragma mark - parameters append method
// 设置HLAPI的requestDelegate
- (__kindof HLURLRequest *(^)(id<HLURLRequestDelegate> _Nullable delegate))setDelegate;
// 设置API的baseURL,该参数会覆盖config中的baseURL
- (__kindof HLURLRequest *(^)(NSString *baseURL))setBaseURL;
// urlQuery,baseURL后的地址
- (__kindof HLURLRequest *(^)(NSString * _Nullable path))setPath;
// 自定义的RequestUrl,该参数会无视任何baseURL的设置,优先级最高
- (__kindof HLURLRequest *(^)(NSString *customURL))setCustomURL;
// HTTPS 请求的Security策略
- (__kindof HLURLRequest *(^)(HLSecurityPolicyConfig *securityPolicy))setSecurityPolicy;
// HTTP 请求的Cache策略
- (__kindof HLURLRequest *(^)(NSURLRequestCachePolicy requestCachePolicy))setCachePolicy;
// HTTP 请求超时的时间,默认为15秒
- (__kindof HLURLRequest *(^)(NSTimeInterval requestTimeoutInterval))setTimeout;
#pragma mark - process
// 开启API 请求
- (__kindof HLURLRequest *)start;
// 取消API 请求
- (__kindof HLURLRequest *)cancel;
// 继续Task
- (__kindof HLURLRequest *)resume;
// 暂停Task
- (__kindof HLURLRequest *)pause;
#pragma mark - helper
- (NSDictionary *)toDictionary;
- (NSString *)hashKey;
@end
#pragma mark - handler block function
@interface HLURLRequest (Handler)
/**
API完成后的成功回调
写法:
.success(^(id obj) {
dosomething
})
*/
- (__kindof HLURLRequest *(^)(HLSuccessBlock))success;
/**
API完成后的失败回调
写法:
.failure(^(NSError *error) {
})
*/
- (__kindof HLURLRequest *(^)(HLFailureBlock))failure;
/**
API上传、下载等长时间执行的Progress进度
写法:
.progress(^(NSProgress *proc){
NSLog(@"当前进度:%@", proc);
})
*/
- (__kindof HLURLRequest *(^)(HLProgressBlock))progress;
/**
用于Debug的Block
block内返回HLDebugMessage对象
*/
- (__kindof HLURLRequest *(^)(HLDebugBlock))debug;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Generator/Request/Base/HLURLRequest.m
================================================
//
// HLURLRequest.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLRequest.h"
#import "HLURLRequest_InternalParams.h"
#import "HLNetworkConfig.h"
#import "HLNetworkMacro.h"
#import "HLNetworkManager.h"
#import "HLSecurityPolicyConfig.h"
@implementation HLURLRequest
#pragma mark - initialize method
- (instancetype)init {
self = [super init];
if (self) {
_cURL = nil;
_path = nil;
_baseURL = [HLNetworkManager config].request.baseURL;
_timeoutInterval = HL_API_REQUEST_TIME_OUT;
_retryCount = [HLNetworkManager config].request.retryCount;
_cachePolicy = NSURLRequestUseProtocolCachePolicy;
_securityPolicy = [HLNetworkManager config].defaultSecurityPolicy;
}
return self;
}
+ (instancetype)request {
return [[self alloc] init];
}
- (id)copyWithZone:(NSZone *)zone {
HLURLRequest *request = [[[self class] alloc] init];
if (request) {
request.cURL = [_cURL copyWithZone:zone];
request.path = [_path copyWithZone:zone];
request.baseURL = [_baseURL copyWithZone:zone];
request.timeoutInterval = _timeoutInterval;
request.retryCount = _retryCount;
request.securityPolicy = [_securityPolicy copyWithZone:zone];
request.cachePolicy = _cachePolicy;
request.delegate = _delegate;
}
return request;
}
#pragma mark - parameters append method
// 设置HLAPI的requestDelegate
- (__kindof HLURLRequest *(^)(id<HLURLRequestDelegate> delegate))setDelegate {
return ^HLURLRequest* (id<HLURLRequestDelegate> delegate) {
self.delegate = delegate;
return self;
};
}
// 设置API的baseURL,该参数会覆盖config中的baseURL
- (__kindof HLURLRequest *(^)(NSString *baseURL))setBaseURL {
return ^HLURLRequest* (NSString *baseURL) {
self.baseURL = baseURL;
return self;
};
}
// urlQuery,baseURL后的地址
- (__kindof HLURLRequest *(^)(NSString *path))setPath {
return ^HLURLRequest* (NSString *path) {
self.path = path;
return self;
};
}
// 自定义的RequestUrl,该参数会无视任何baseURL的设置,优先级最高
- (__kindof HLURLRequest *(^)(NSString *customURL))setCustomURL {
return ^HLURLRequest* (NSString *customURL) {
self.cURL = customURL;
NSURL *tmpURL = [NSURL URLWithString:customURL];
if (tmpURL.host) {
self.baseURL = [NSString stringWithFormat:@"%@://%@", tmpURL.scheme ?: @"https", tmpURL.host];
self.path = [NSString stringWithFormat:@"%@", tmpURL.query];
}
return self;
};
}
// HTTPS 请求的Security策略
- (__kindof HLURLRequest *(^)(HLSecurityPolicyConfig *securityPolicy))setSecurityPolicy {
return ^HLURLRequest* (HLSecurityPolicyConfig *securityPolicy) {
self.securityPolicy = securityPolicy;
return self;
};
}
// HTTP 请求的Cache策略
- (__kindof HLURLRequest *(^)(NSURLRequestCachePolicy requestCachePolicy))setCachePolicy {
return ^HLURLRequest* (NSURLRequestCachePolicy requestCachePolicy) {
self.cachePolicy = requestCachePolicy;
return self;
};
}
// HTTP 请求超时的时间,默认为15秒
- (__kindof HLURLRequest *(^)(NSTimeInterval requestTimeoutInterval))setTimeout {
return ^HLURLRequest* (NSTimeInterval requestTimeoutInterval) {
self.timeoutInterval = requestTimeoutInterval;
return self;
};
}
#pragma mark - handler block function
/**
API完成后的成功回调
写法:
.success(^(id obj) {
dosomething
})
*/
- (__kindof HLURLRequest *(^)(HLSuccessBlock))success {
return ^HLURLRequest* (HLSuccessBlock objBlock) {
self.successHandler = objBlock;
return self;
};
}
/**
API完成后的失败回调
写法:
.failure(^(NSError *error) {
})
*/
- (__kindof HLURLRequest *(^)(HLFailureBlock))failure {
return ^HLURLRequest* (HLFailureBlock errorBlock) {
self.failureHandler = errorBlock;
return self;
};
}
/**
API上传、下载等长时间执行的Progress进度
写法:
.progress(^(NSProgress *proc){
NSLog(@"当前进度:%@", proc);
})
*/
- (__kindof HLURLRequest *(^)(HLProgressBlock))progress {
return ^HLURLRequest* (HLProgressBlock progressBlock) {
self.progressHandler = progressBlock;
return self;
};
}
/**
用于Debug的Block
block内返回HLDebugMessage对象
*/
- (__kindof HLURLRequest *(^)(HLDebugBlock))debug {
return ^HLURLRequest* (HLDebugBlock debugBlock) {
self.debugHandler = debugBlock;
return self;
};
}
#pragma mark - process
// 开启API 请求
- (__kindof HLURLRequest *)start {
[HLNetworkManager send:self];
return self;
}
// 取消API 请求
- (__kindof HLURLRequest *)cancel {
[HLNetworkManager cancel:self];
return self;
}
// 继续Task
- (__kindof HLURLRequest *)resume {
[HLNetworkManager resume:self];
return self;
}
// 暂停Task
- (__kindof HLURLRequest *)pause {
[HLNetworkManager pause:self];
return self;
}
#pragma mark - helper
- (NSDictionary *)toDictionary {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"APIVersion"] = [HLNetworkManager config].request.apiVersion ?: @"未设置";
dict[@"BaseURL"] = self.baseURL ?: [HLNetworkManager config].request.baseURL;
dict[@"Path"] = self.path ?: @"未设置";
dict[@"CustomURL"] = self.customURL ?: @"未设置";
dict[@"TimeoutInterval"] = [NSString stringWithFormat:@"%f", self.timeoutInterval];
dict[@"SecurityPolicy"] = [self.securityPolicy toDictionary];
dict[@"CachePolicy"] = [self getCachePolicy:self.cachePolicy];
return dict;
}
- (NSString *)hashKey {
return [NSString stringWithFormat:@"%lu", (unsigned long)[self hash]];
}
- (NSUInteger)hash {
NSString *hashStr = nil;
if (self.customURL) {
hashStr = [NSString stringWithFormat:@"%@",
self.customURL];
} else {
hashStr = [NSString stringWithFormat:@"%@/%@",
self.baseURL,
self.path];
}
return [hashStr hash];
}
- (BOOL)isEqualToRequest:(HLURLRequest *)request {
return [self hash] == [request hash];
}
- (BOOL)isEqual:(id)object {
if (self == object) return YES;
if (![object isKindOfClass:[HLURLRequest class]]) return NO;
return [self isEqualToRequest:(HLURLRequest *) object];
}
- (NSString *)getCachePolicy:(NSURLRequestCachePolicy)policy {
switch (policy) {
case NSURLRequestUseProtocolCachePolicy:
return @"NSURLRequestUseProtocolCachePolicy";
break;
case NSURLRequestReloadIgnoringLocalCacheData:
return @"NSURLRequestReloadIgnoringLocalCacheData";
break;
case NSURLRequestReloadIgnoringLocalAndRemoteCacheData:
return @"NSURLRequestReloadIgnoringLocalAndRemoteCacheData";
break;
case NSURLRequestReturnCacheDataElseLoad:
return @"NSURLRequestReturnCacheDataElseLoad";
break;
case NSURLRequestReturnCacheDataDontLoad:
return @"NSURLRequestReturnCacheDataDontLoad";
break;
case NSURLRequestReloadRevalidatingCacheData:
return @"NSURLRequestReloadRevalidatingCacheData";
break;
default:
return @"NULL";
break;
}
}
@end
================================================
FILE: HLNetworking/Source/Generator/Request/Base/HLURLRequest_InternalParams.h
================================================
//
// HLURLRequest_InternalParams.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLRequest.h"
NS_ASSUME_NONNULL_BEGIN
@interface HLURLRequest ()
@property (nonatomic, weak, nullable) id<HLURLRequestDelegate> delegate;
@property (nonatomic, copy) NSString *cURL;
@property (nonatomic, copy) NSString *baseURL;
@property (nonatomic, copy) NSString *path;
@property (nonatomic, assign)NSTimeInterval timeoutInterval;
@property (nonatomic, assign)NSURLRequestCachePolicy cachePolicy;
@property (nonatomic, strong)HLSecurityPolicyConfig *securityPolicy;
@property (nonatomic, copy, nullable) HLSuccessBlock successHandler;
@property (nonatomic, copy, nullable) HLFailureBlock failureHandler;
@property (nonatomic, copy, nullable) HLProgressBlock progressHandler;
@property (nonatomic, copy, nullable) HLDebugBlock debugHandler;
@property (nonatomic, assign) NSUInteger retryCount;
@property (nonatomic, strong, nullable) dispatch_queue_t queue;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Generator/Request/Group/HLRequestGroup.h
================================================
//
// HLRequestGroup.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
@class HLURLRequest;
@class HLRequestGroup;
typedef NS_ENUM(NSUInteger, HLRequestGroupMode) {
HLRequestGroupModeBatch,
HLRequestGroupModeChain
};
NS_ASSUME_NONNULL_BEGIN
@protocol HLRequestGroupDelegate <NSObject>
// Requests 全部调用完成之后调用
- (void)requestGroupAllDidFinished:(nonnull HLRequestGroup *)apiGroup;
@end
@interface HLRequestGroup : NSObject
// 请求组类型
@property (nonatomic, assign, readonly) HLRequestGroupMode groupMode;
@property (nonatomic, assign) NSUInteger maxRequestCount;
// 自定义的同步请求所在的串行队列
@property (nonatomic, strong, readonly) dispatch_queue_t customQueue;
// Group 内 api 执行完成之后调用的delegate
@property (nonatomic, weak, nullable) id<HLRequestGroupDelegate> delegate;
// 请使用manager或sharedManager
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
// 返回一个新的manager对象
+ (instancetype)groupWithMode:(HLRequestGroupMode)mode;
// 加入到group集合中
- (void)add:(nonnull __kindof HLURLRequest *)request;
// 将带有API集合的Array 赋值
- (void)addRequests:(nonnull NSArray<__kindof HLURLRequest *> *)requests;
// 开启队列请求
- (void)start;
// 取消所有请求
- (void)cancel;
// 设置组GCD队列
- (dispatch_queue_t)setupGroupQueue:(NSString *)queueName;
#pragma mark - 遍历方法
@property (readonly) NSUInteger count;
- (void)enumerateObjectsUsingBlock:(void (^)(__kindof HLURLRequest *request, NSUInteger idx, BOOL * stop))block;
- (nonnull NSEnumerator*)objectEnumerator;
- (nonnull id)objectAtIndexedSubscript:(NSUInteger)idx;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Generator/Request/Group/HLRequestGroup.m
================================================
//
// HLRequestGroup.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLRequestGroup.h"
#import "HLURLRequest.h"
#import "HLNetworkManager.h"
#define mix(A, B) A##B
// 创建任务队列
static dispatch_queue_t qkhl_api_chain_queue(const char * queueName) {
static dispatch_queue_t mix(qkhl_api_chain_queue_, queueName);
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mix(qkhl_api_chain_queue_, queueName) =
dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
});
return mix(qkhl_api_chain_queue_, queueName);
}
@interface HLRequestGroup ()
@property (nonatomic, strong, readwrite) NSMutableArray <__kindof HLURLRequest *>*apiArray;
// 自定义的同步请求所在的串行队列
@property (nonatomic, strong, readwrite) dispatch_queue_t customQueue;
@end
@implementation HLRequestGroup
#pragma mark - initialize method
- (instancetype)initWithMode:(HLRequestGroupMode)mode {
self = [super init];
if (self) {
_apiArray = [NSMutableArray array];
_groupMode = mode;
_maxRequestCount = 1;
}
return self;
}
+ (instancetype)groupWithMode:(HLRequestGroupMode)mode {
return [[self alloc] initWithMode:mode];
}
#pragma mark - NSFastEnumeration
- (NSUInteger)count {
return _apiArray.count;
}
- (nonnull id)objectAtIndexedSubscript:(NSUInteger)idx {
if (idx >= _apiArray.count) {
[NSException raise:NSRangeException format:@"Index %lu 的区间为 [0, %lu].", (unsigned long)idx, (unsigned long)_apiArray.count];
}
return _apiArray[idx];
}
- (void)enumerateObjectsUsingBlock:(void (^)(__kindof HLURLRequest *request, NSUInteger idx, BOOL *stop))block {
[_apiArray enumerateObjectsUsingBlock:block];
}
- (NSEnumerator*)objectEnumerator {
return [_apiArray objectEnumerator];
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(id _Nullable __unsafe_unretained [])buffer
count:(NSUInteger)len
{
return [_apiArray countByEnumeratingWithState:state objects:buffer count:len];
}
#pragma mark - Add Requests
- (void)add:(__kindof HLURLRequest *)request {
if (!request) {
return;
}
if ([self.apiArray containsObject:request]) {
#ifdef DEBUG
NSLog(@"批处理队列中已有相同的API!");
#endif
}
[self.apiArray addObject:request];
}
- (void)addRequests:(nonnull NSArray<__kindof HLURLRequest *> *)requests {
if (!requests) return;
if (requests.count == 0) return;
[requests enumerateObjectsUsingBlock:^(HLURLRequest * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self add:obj];
}];
}
- (void)start {
if (self.apiArray.count == 0) return;
[HLNetworkManager sendGroup:self];
}
- (void)cancel {
if (self.apiArray.count == 0) return;
[HLNetworkManager cancelGroup:self];
}
- (dispatch_queue_t)setupGroupQueue:(NSString *)queueName {
self.customQueue = qkhl_api_chain_queue([queueName UTF8String]);
return self.customQueue;
}
@end
================================================
FILE: HLNetworking/Source/Generator/Request/Task/HLTaskRequest.h
================================================
//
// HLTaskRequest.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLRequest.h"
NS_ASSUME_NONNULL_BEGIN
@interface HLTaskRequest : HLURLRequest
#pragma mark - property
@property (nonatomic, copy, readonly) NSString *filePath;
@property (nonatomic, copy, readonly) NSString *resumePath;
#pragma mark - parameters append method
// 设置下载或者上传的本地文件路径
- (HLTaskRequest *(^)(NSString *filePath))setFilePath;
// 设置task的类型(上传/下载)
- (HLTaskRequest *(^)(HLRequestTaskType requestTaskType))setTaskType;
#pragma mark - process
// 开启API 请求
- (HLTaskRequest *)start;
// 取消API 请求
- (HLTaskRequest *)cancel;
// 继续Task
- (HLTaskRequest *)resume;
// 暂停Task
- (HLTaskRequest *)pause;
#pragma mark - 重写父类方法,用于转换类型
// 设置HLAPI的requestDelegate
- (HLTaskRequest *(^)(id<HLURLRequestDelegate> delegate))setDelegate;
// 设置API的baseURL,该参数会覆盖config中的baseURL
- (HLTaskRequest *(^)(NSString *baseURL))setBaseURL;
// urlQuery,baseURL后的地址
- (HLTaskRequest *(^)(NSString *path))setPath;
// 自定义的RequestUrl,该参数会无视任何baseURL的设置,优先级最高
- (HLTaskRequest *(^)(NSString *customURL))setCustomURL;
// HTTPS 请求的Security策略
- (HLTaskRequest *(^)(HLSecurityPolicyConfig *securityPolicy))setSecurityPolicy;
// HTTP 请求的Cache策略
- (HLTaskRequest *(^)(NSURLRequestCachePolicy requestCachePolicy))setCachePolicy;
// HTTP 请求超时的时间,默认为15秒
- (HLTaskRequest *(^)(NSTimeInterval requestTimeoutInterval))setTimeout;
/**
API完成后的成功回调
写法:
.success(^(id obj) {
dosomething
})
*/
- (HLTaskRequest *(^)(HLSuccessBlock))success;
/**
API完成后的失败回调
写法:
.failure(^(NSError *error) {
})
*/
- (HLTaskRequest *(^)(HLFailureBlock))failure;
/**
API上传、下载等长时间执行的Progress进度
写法:
.progress(^(NSProgress *proc){
NSLog(@"当前进度:%@", proc);
})
*/
- (HLTaskRequest *(^)(HLProgressBlock))progress;
/**
用于Debug的Block
block内返回HLDebugMessage对象
*/
- (HLTaskRequest *(^)(HLDebugBlock))debug;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Generator/Request/Task/HLTaskRequest.m
================================================
//
// HLTaskRequest.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLTaskRequest_InternalParams.h"
#import "HLURLRequest_InternalParams.h"
#import "HLNetworkManager.h"
#import "HLNetworkConfig.h"
#import "HLSecurityPolicyConfig.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-implementation"
@implementation HLTaskRequest
#pragma mark - initialize method
- (instancetype)init {
self = [super init];
if (self) {
_requestTaskType = Download;
NSString *baseResumePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"com.qkhl.HLNetworking/downloadDict"];
if (![[NSFileManager defaultManager] fileExistsAtPath:baseResumePath isDirectory:nil]) {
[[NSFileManager defaultManager] createDirectoryAtPath:baseResumePath withIntermediateDirectories:YES attributes:nil error:nil];
}
_resumePath = [baseResumePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%lu.arc", (unsigned long)self.hash]];
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
HLTaskRequest *request = [super copyWithZone:zone];
if (request) {
request.filePath = [_filePath copyWithZone:zone];
request.resumePath = [_resumePath copyWithZone:zone];
request.requestTaskType = _requestTaskType;
}
return request;
}
#pragma mark - parameters append method
// 设置下载或者上传的本地文件路径
- (HLTaskRequest *(^)(NSString *filePath))setFilePath {
return ^HLTaskRequest* (NSString *filePath) {
self.filePath = filePath;
return self;
};
}
// 设置task的类型(上传/下载)
- (HLTaskRequest *(^)(HLRequestTaskType requestTaskType))setTaskType {
return ^HLTaskRequest* (HLRequestTaskType requestTaskType) {
self.requestTaskType = requestTaskType;
return self;
};
}
#pragma mark - helper
- (NSUInteger)hash {
NSString *hashStr;
if (self.customURL) {
hashStr = self.customURL;
} else {
hashStr = [NSString stringWithFormat:@"%@/%@", self.baseURL, self.path];
}
return [hashStr hash];
}
- (NSString *)description {
NSMutableString *desc = [NSMutableString string];
#if DEBUG
[desc appendString:@"\n===============HLTask Start===============\n"];
[desc appendFormat:@"Class: %@\n", self.class];
[desc appendFormat:@"BaseURL: %@\n", self.baseURL ?: [HLNetworkManager config].request.baseURL];
[desc appendFormat:@"Path: %@\n", self.path ?: @"未设置"];
[desc appendFormat:@"CustomURL: %@\n", self.customURL ?: @"未设置"];
[desc appendFormat:@"ResumePath: %@", self.resumePath];
[desc appendFormat:@"CachePath: %@", self.filePath];
[desc appendFormat:@"TimeoutInterval: %f\n", self.timeoutInterval];
[desc appendFormat:@"SecurityPolicy: %@\n", self.securityPolicy];
[desc appendFormat:@"RequestTaskType: %@\n", [self getRequestTaskTypeString:self.requestTaskType]];
[desc appendFormat:@"CachePolicy: %@\n", [self getCachePolicyString:self.cachePolicy]];
[desc appendString:@"===============End===============\n"];
#else
desc = [NSMutableString stringWithFormat:@""];
#endif
return desc;
}
- (NSString *)getRequestTaskTypeString:(HLRequestTaskType)type {
switch (type) {
case Download:
return @"Download";
break;
case Upload:
return @"Upload";
break;
default:
return @"Download";
break;
}
}
- (NSString *)getCachePolicyString:(NSURLRequestCachePolicy)policy {
switch (policy) {
case NSURLRequestUseProtocolCachePolicy:
return @"NSURLRequestUseProtocolCachePolicy";
break;
case NSURLRequestReloadIgnoringLocalCacheData:
return @"NSURLRequestReloadIgnoringLocalCacheData";
break;
case NSURLRequestReloadIgnoringLocalAndRemoteCacheData:
return @"NSURLRequestReloadIgnoringLocalAndRemoteCacheData";
break;
case NSURLRequestReturnCacheDataElseLoad:
return @"NSURLRequestReturnCacheDataElseLoad";
break;
case NSURLRequestReturnCacheDataDontLoad:
return @"NSURLRequestReturnCacheDataDontLoad";
break;
case NSURLRequestReloadRevalidatingCacheData:
return @"NSURLRequestReloadRevalidatingCacheData";
break;
default:
return @"NSURLRequestUseProtocolCachePolicy";
break;
}
}
- (NSDictionary *)toDictionary {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"APIVersion"] = [HLNetworkManager config].request.apiVersion ?: @"未设置";
dict[@"BaseURL"] = self.baseURL ?: [HLNetworkManager config].request.baseURL;
dict[@"Path"] = self.path ?: @"未设置";
dict[@"CustomURL"] = self.customURL ?: @"未设置";
dict[@"ResumePath"] = self.resumePath ?: @"未设置";
dict[@"TimeoutInterval"] = [NSString stringWithFormat:@"%f", self.timeoutInterval];
dict[@"SecurityPolicy"] = [self.securityPolicy toDictionary];
dict[@"RequestMethodType"] = [self getRequestTaskTypeString:self.requestTaskType];
dict[@"CachePolicy"] = [self getCachePolicyString:self.cachePolicy];
return dict;
}
@end
#pragma clang diagnostic pop
================================================
FILE: HLNetworking/Source/Generator/Request/Task/HLTaskRequest_InternalParams.h
================================================
//
// HLTaskRequest_InternalParams.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLTaskRequest.h"
@interface HLTaskRequest ()
@property (nonatomic, copy) NSString *filePath;
@property (nonatomic, copy) NSString *resumePath;
@property (nonatomic, assign)HLRequestTaskType requestTaskType;
@end
================================================
FILE: HLNetworking/Source/Generator/Response/HLURLResponse.h
================================================
//
// HLURLResponse.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLURLResult.h"
@interface HLURLResponse : NSObject
@property (nonatomic, strong, readonly) HLURLResult *result;
@property (nonatomic, assign, readonly) NSUInteger requestId;
@property (nonatomic, copy, readonly) NSURLRequest *request;
- (NSDictionary *)toDictionary;
- (instancetype)initWithResult:(HLURLResult *)result
requestId:(NSNumber *)requestId
request:(NSURLRequest *)request;
@end
================================================
FILE: HLNetworking/Source/Generator/Response/HLURLResponse.m
================================================
//
// HLURLResponse.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLResponse.h"
@interface HLURLResponse ()
@property (nonatomic, strong, readwrite) HLURLResult *result;
@property (nonatomic, copy, readwrite) NSURLRequest *request;
@property (nonatomic, assign, readwrite) NSUInteger requestId;
@end
@implementation HLURLResponse
#pragma mark - life cycle
- (instancetype)initWithResult:(HLURLResult *)result
requestId:(NSNumber *)requestId
request:(NSURLRequest *)request
{
self = [super init];
if (self) {
_result = result;
_requestId = [requestId integerValue];
_request = request;
}
return self;
}
#pragma mark - private methods
- (NSString *)description {
NSMutableString *desc = [NSMutableString string];
[desc appendString:@"\n++++++++HLURLResponse Start++++++++\n"];
[desc appendFormat:@"Result : %@\n", self.result];
[desc appendFormat:@"Request : %@\n", self.request];
[desc appendFormat:@"RequestId : %lu\n", (unsigned long)self.requestId];
[desc appendString:@"+++++++++HLURLResponse End+++++++++\n"];
return desc;
}
- (NSDictionary *)toDictionary {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"Result"] = [self.result toDictionary];
dict[@"Request"] = self.request.description;
dict[@"RequestId"] = [NSString stringWithFormat:@"%lu", (unsigned long)self.requestId];
return dict;
}
- (NSString *)debugDescription {
return self.description;
}
@end
================================================
FILE: HLNetworking/Source/Generator/Result/HLURLResult.h
================================================
//
// HLURLResult.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, HLURLResultStatus) {
HLURLResultStatusSuccess, //作为底层,请求是否成功只考虑是否成功收到服务器反馈。至于签名是否正确,返回的数据是否完整,由上层的CTAPIBaseManager来决定。
HLURLResultStatusErrorTimeout,
HLURLResultStatusErrorNotReachable // 默认除了超时以外的错误都是无网络错误。
};
@interface HLURLResult : NSObject
@property (nonatomic, strong, readonly) id resultObject;
@property (nonatomic, strong, readonly) NSError *error;
@property (nonatomic, assign, readonly) HLURLResultStatus status;
- (NSDictionary *)toDictionary;
- (instancetype)initWithObject:(id)resultObject andError:(NSError *)error;
@end
================================================
FILE: HLNetworking/Source/Generator/Result/HLURLResult.m
================================================
//
// HLURLResult.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLURLResult.h"
@interface HLURLResult ()
@property (nonatomic, strong, readwrite) id resultObject;
@property (nonatomic, strong, readwrite) NSError *error;
@property (nonatomic, assign, readwrite) HLURLResultStatus status;
@end
@implementation HLURLResult
- (instancetype)initWithObject:(id)resultObject andError:(NSError *)error {
self = [super init];
if (self) {
_resultObject = resultObject;
_error = error;
_status = [self resultStatusWithError:error];
}
return self;
}
- (HLURLResultStatus)resultStatusWithError:(NSError *)error {
if (error) {
HLURLResultStatus result = HLURLResultStatusErrorNotReachable;
// 除了超时以外,所有错误都当成是无网络
if (error.code == NSURLErrorTimedOut) {
result = HLURLResultStatusErrorTimeout;
}
return result;
} else {
return HLURLResultStatusSuccess;
}
}
- (NSString *)description {
NSMutableString *desc = [NSMutableString string];
[desc appendString:@"\n---------HLURLResult Start---------\n"];
[desc appendFormat:@"Status : %@\n", [self getHLURLResultStatusString:self.status]];
[desc appendFormat:@"Object : %@\n", self.resultObject];
[desc appendFormat:@"Error : %@\n", self.error ?: @"成功"];
[desc appendString:@"----------HLURLResult End----------"];
return desc;
}
- (NSString *)debugDescription {
return self.description;
}
- (NSDictionary *)toDictionary {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[@"Status"] = [self getHLURLResultStatusString:self.status];
dict[@"Object"] = [NSString stringWithFormat:@"%@", [self.resultObject class]];
dict[@"Error"] = self.error.localizedDescription ?: @"无错误";
return dict;
}
- (NSString *)getHLURLResultStatusString:(HLURLResultStatus)status {
switch (status) {
case HLURLResultStatusSuccess:
return @"HLURLResultStatusSuccess";
break;
case HLURLResultStatusErrorTimeout:
return @"HLURLResultStatusErrorTimeout";
break;
case HLURLResultStatusErrorNotReachable:
return @"HLURLResultStatusErrorNotReachable";
break;
default:
return @"HLURLResultStatusErrorUnknown";
break;
}
}
@end
================================================
FILE: HLNetworking/Source/HLNetworking.h
================================================
//
// HLNetworking.h
// HLPPShop
//
// Created by wangshiyu13 on 2016/9/19.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#ifndef HLNetworking_h
#define HLNetworking_h
// config
#import "HLNetworkMacro.h"
#import "HLNetworkConst.h"
#import "HLNetworkConfig.h"
#import "HLSecurityPolicyConfig.h"
// manager
#import "HLNetworkManager.h"
// request
#import "HLURLRequest.h"
#import "HLRequestGroup.h"
#import "HLAPIRequest.h"
#import "HLTaskRequest.h"
// logger
#import "HLNetworkLogger.h"
#endif /* HLNetworking_h */
================================================
FILE: HLNetworking/Source/Logger/HLDebugMessage.h
================================================
//
// HLDebugMessage.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLURLResponse.h"
#import "NSNull+ToDictionary.h"
typedef NSString *HLDebugKey;
@interface HLDebugMessage : NSObject
// 请求对象,HLAPI或HLTask
@property (nonatomic, strong, readonly)id requestObject;
// 获取NSURLSessionTask
@property (nonatomic, strong, readonly)NSURLSessionTask *sessionTask;
// 获取RequestObject
@property (nonatomic, strong, readonly)HLURLResponse *response;
// 执行的队列名
@property (nonatomic, copy, readonly)NSString *queueName;
// 生成时间
@property (nonatomic, copy, readonly) NSString *timeString;
- (instancetype)initWithRequest:(id)requestObject andResult:(id)resultObject andError:(NSError *)error andQueueName:(NSString *)queueName;
- (NSDictionary *)toDictionary;
@end
================================================
FILE: HLNetworking/Source/Logger/HLDebugMessage.m
================================================
//
// HLDebugMessage.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/2.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLDebugMessage.h"
#import "HLNetworkEngine.h"
HLDebugKey const kHLSessionTaskDebugKey = @"kHLSessionTaskDebugKey";
HLDebugKey const kHLRequestDebugKey = @"kHLRequestDebugKey";
HLDebugKey const kHLResponseDebugKey = @"kHLResponseDebugKey";
HLDebugKey const kHLQueueDebugKey = @"kHLQueueDebugKey";
@interface HLDebugMessage ()
// 获取NSURLSessionTask
@property (nonatomic, strong, readwrite)NSURLSessionTask *sessionTask;
// 获取HLAPI
@property (nonatomic, strong, readwrite)id requestObject;
// 获取NSURLResponse
@property (nonatomic, strong, readwrite)HLURLResponse *response;
// 执行的队列名
@property (nonatomic, copy, readwrite)NSString *queueName;
// 生成时间
@property (nonatomic, copy, readwrite) NSString *timeString;
@end
@implementation HLDebugMessage
- (instancetype)initWithRequest:(id)requestObject andResult:(id)resultObject andError:(NSError *)error andQueueName:(NSString *)queueName {
self = [super init];
if (self) {
NSDateFormatter *myFormatter = [[NSDateFormatter alloc] init];
[myFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
_timeString = [myFormatter stringFromDate:[NSDate date]];
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wundeclared-selector"
NSString *hashKey = [requestObject performSelector:@selector(hashKey)];
#pragma clang diagnostic pop
id sessionTask = [[HLNetworkEngine sharedEngine] requestByIdentifier: hashKey];
id request = [NSNull null];
id requestId = [NSNull null];
if ([requestObject isKindOfClass:[NSURLSessionTask class]]) {
request = [sessionTask currentRequest];
}
if ([requestObject hash]) {
requestId = [NSNumber numberWithUnsignedInteger:[requestObject hash]];
}
// 生成response对象
HLURLResult *result = [[HLURLResult alloc] initWithObject:resultObject andError:error];
HLURLResponse *response = [[HLURLResponse alloc] initWithResult:result
requestId:requestId
request:request];
_sessionTask = sessionTask;
_requestObject = request;
_response = response;
_queueName = queueName;
}
return self;
}
- (NSDictionary *)toDictionary {
NSMutableDictionary <NSString *, id>*dictionary = [NSMutableDictionary dictionary];
dictionary[@"Time"] = self.timeString;
dictionary[@"RequestObject"] = [self.requestObject toDictionary];
dictionary[@"Response"] = [self.response toDictionary];
dictionary[@"SessionTask"] = [self.sessionTask description];
dictionary[@"Queue"] = self.queueName;
return dictionary;
}
- (NSString *)description {
NSMutableString *desc = [NSMutableString string];
[desc appendString:@"\n****************Debug Message Start****************\n"];
[desc appendFormat:@"Time : %@\n", self.timeString];
[desc appendFormat:@"RequestObject : %@\n", self.requestObject ?: @"无参数"];
[desc appendFormat:@"SessionTask : %@\n", self.sessionTask ?: @"无参数"];
[desc appendFormat:@"Response : %@\n", self.response ?: @"无参数"];
[desc appendFormat:@"Queue : %@", self.queueName ?: @"无参数"];
[desc appendString:@"\n****************Debug Message End****************\n"];
return desc;
}
- (NSString *)debugDescription {
return self.description;
}
@end
================================================
FILE: HLNetworking/Source/Logger/HLNetworkLogger.h
================================================
//
// HLNetworkLogger.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HLNetworkLoggerConfig.h"
#import "HLDebugMessage.h"
#import "UIDevice+deviceInfo.h"
NS_ASSUME_NONNULL_BEGIN
@protocol HLNetworkCustomLoggerDelegate <NSObject>
@required
// 根据传入的message拼接存储的日志结构
- (NSDictionary *)customInfoWithMessage:(HLDebugMessage *)message;
@optional
// 根据传入的设置拼接日志头部信息
- (NSDictionary *)customHeaderWithMessage:(HLNetworkLoggerConfig *)config;
@end
@interface HLNetworkLogger : NSObject
@property (nonatomic, strong, readonly) HLNetworkLoggerConfig *config;
// 设置代理
+ (void)setDelegate:(id<HLNetworkCustomLoggerDelegate>)delegate;
// 写入后会清空当前记录的日志
+ (void)writeToFile;
// 打印debugMessage,该方法只在debug模式下有效
+ (void)logInfoWithDebugMessage:(HLDebugMessage *)debugMessage;
// 添加日志
+ (void)addLogInfoWithDictionary:(NSDictionary *)dictionary;
// 日志文件路径数组
+ (nullable NSArray <NSString *>*)logFilePaths;
// 设置config
+ (void)setupConfig:(void(^)(HLNetworkLoggerConfig *config))configBlock;
// 是否已经开启日志
+ (BOOL)isEnable;
// 开启日志
+ (void)startLogging;
// 关闭日志
+ (void)stopLogging;
// 当前代理对象
+ (nullable id<HLNetworkCustomLoggerDelegate>)currentDelegate;
// 单例对象
+ (instancetype)shared;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Logger/HLNetworkLogger.m
================================================
//
// HLNetworkLogger.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLNetworkLogger.h"
#import "HLNetworkMacro.h"
#import "UIDevice+deviceInfo.h"
// 创建任务队列
static dispatch_queue_t qkhl_log_queue() {
static dispatch_queue_t qkhl_log_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
qkhl_log_queue =
dispatch_queue_create("com.qkhl.networking.wangshiyu13.log.queue", DISPATCH_QUEUE_SERIAL);
});
return qkhl_log_queue;
}
@interface HLNetworkLogger ()
@property (nonatomic, strong, readwrite) HLNetworkLoggerConfig *config;
@property (nonatomic, weak, nullable) id<HLNetworkCustomLoggerDelegate> delegate;
@property (nonatomic, assign) BOOL enable;
@property (nonatomic, strong) NSMutableArray <NSDictionary *>*debugInfoArray;
@end
@implementation HLNetworkLogger
#pragma mark - logger
- (id<HLNetworkCustomLoggerDelegate>)currentDelegate {
return [self delegate];
}
- (void)logInfoWithDebugMessage:(HLDebugMessage *)debugMessage {
#if DEBUG
NSLog(@"%@", debugMessage);
#endif
}
- (NSArray <NSString *>*)logFilePaths {
NSString *dirPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"com.qkhl.HLNetworking/log"];
NSArray <NSString *>*fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:nil];
NSMutableArray <NSString *>*tmpArray = [NSMutableArray array];
for (NSString *fileName in fileList) {
NSString *path = [NSString stringWithFormat:@"%@/%@", dirPath, fileName];
[tmpArray addObject:path];
}
return [tmpArray copy];
}
- (void)writeToFile {
dispatch_async(qkhl_log_queue(), ^{
if (self.config.enableLocalLog) {
BOOL succeed = NO;
if (self.config.loggerType == HLNetworkLoggerTypeJSON) {
NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:self.config.logFilePath append:YES];
[outputStream open];
succeed = [NSJSONSerialization writeJSONObject:self.debugInfoArray toStream:outputStream options:NSJSONWritingPrettyPrinted error:nil];
[outputStream close];
} else {
succeed = [self.debugInfoArray writeToFile:self.config.logFilePath atomically:YES];
}
if (succeed) {
[self.debugInfoArray removeAllObjects];
}
}
});
}
- (void)addLogInfoWithDictionary:(NSDictionary *)dictionary {
dispatch_async(qkhl_log_queue(), ^{
if (self.config.enableLocalLog) {
if (self.debugInfoArray.count > self.config.logAutoSaveCount) {
[self writeToFile];
}
if (dictionary.count > 0) {
[self.debugInfoArray addObject:dictionary];
}
}
});
}
- (void)startLogging {
self.enable = YES;
}
- (void)stopLogging {
self.enable = NO;
}
#pragma mark - setupConfig
- (void)setupConfig:(void (^)(HLNetworkLoggerConfig * _Nonnull))configBlock {
HL_SAFE_BLOCK(configBlock, self.config);
}
#pragma mark - init
+ (instancetype)shared {
static dispatch_once_t onceToken;
static HLNetworkLogger *shared;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}
- (instancetype)init {
self = [super init];
if (self) {
_config = [HLNetworkLoggerConfig config];
_enable = NO;
_debugInfoArray = [NSMutableArray array];
}
return self;
}
- (NSMutableArray<NSDictionary *> *)debugInfoArray {
if (_debugInfoArray.count == 0) {
NSDictionary *infoHeader;
if ([self.delegate respondsToSelector:@selector(customHeaderWithMessage:)]) {
infoHeader = [self.delegate customHeaderWithMessage:self.config];
} else {
infoHeader = @{@"AppInfo": @{@"OSVersion": [UIDevice currentDevice].systemVersion,
@"DeviceType": [UIDevice currentDevice].hl_machineType,
@"UDID": [UIDevice currentDevice].hl_udid,
@"UUID": [UIDevice currentDevice].hl_uuid,
@"MacAddressMD5": [UIDevice currentDevice].hl_macaddressMD5,
@"ChannelID": _config.channelID,
@"AppKey": _config.appKey,
@"AppName": _config.appName,
@"AppVersion": _config.appVersion,
@"ServiceType": _config.serviceType}};
}
[_debugInfoArray addObject:infoHeader];
}
return _debugInfoArray;
}
#pragma mark - static method
+ (id<HLNetworkCustomLoggerDelegate>)currentDelegate {
return [[self shared] currentDelegate];
}
+ (void)setDelegate:(id<HLNetworkCustomLoggerDelegate>)delegate {
[[self shared] setDelegate:delegate];
}
+ (NSArray <NSString *>*)logFilePaths {
return [[self shared] logFilePaths];
}
+ (void)setupConfig:(void (^)(HLNetworkLoggerConfig * _Nonnull))configBlock {
[[self shared] setupConfig:configBlock];
}
+ (BOOL)isEnable {
return [[self shared] enable];
}
+ (void)logInfoWithDebugMessage:(HLDebugMessage *)debugMessage {
[[self shared] logInfoWithDebugMessage:debugMessage];
}
+ (void)writeToFile {
[[self shared] writeToFile];
}
+ (void)addLogInfoWithDictionary:(NSDictionary *)dictionary {
[[self shared] addLogInfoWithDictionary:dictionary];
}
+ (void)startLogging {
[[self shared] startLogging];
}
+ (void)stopLogging {
[[self shared] stopLogging];
}
@end
================================================
FILE: HLNetworking/Source/Logger/HLNetworkLoggerConfig.h
================================================
//
// HLNetworkLoggerConfig.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class HLDebugMessage;
typedef NS_OPTIONS(NSUInteger, HLNetworkLoggerLevel) {
HLNetworkLoggerNoneLevel = 0,
HLNetworkLoggerNetErrorLevel = 1 << 0,
HLNetworkLoggerRequestLevel = 1 << 1,
HLNetworkLoggerResponseLevel = 1 << 2,
HLNetworkLoggerAllLevel = 1 << 3
};
typedef NS_ENUM(NSUInteger, HLNetworkLoggerType) {
HLNetworkLoggerTypeJSON,
HLNetworkLoggerTypePlist
};
@interface HLNetworkLoggerConfig : NSObject
// 渠道ID
@property (nonatomic, copy) NSString *channelID;
// app标志
@property (nonatomic, copy) NSString *appKey;
// app名字
@property (nonatomic, copy) NSString *appName;
// app版本
@property (nonatomic, copy) NSString *appVersion;
// 服务名
@property (nonatomic, copy) NSString *serviceType;
// 是否开启本地日志
@property (nonatomic, assign) BOOL enableLocalLog;
// 日志自动保存数,默认为50次保存一次
@property (nonatomic, assign) NSUInteger logAutoSaveCount;
// 日志等级,该选项暂时无效
@property (nonatomic, assign) HLNetworkLoggerLevel loggerLevel;
// 日志保存类型
@property (nonatomic, assign) HLNetworkLoggerType loggerType;
// 日志文件路径
@property (nonatomic, copy, readonly) NSString *logFilePath;
+ (instancetype)config;
@end
================================================
FILE: HLNetworking/Source/Logger/HLNetworkLoggerConfig.m
================================================
//
// HLNetworkLoggerConfig.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/4.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLNetworkLoggerConfig.h"
@interface HLNetworkLoggerConfig ()
// 系统版本
@property (nonatomic, copy, readwrite) NSString *osVersion;
// 设备型号
@property (nonatomic, copy, readwrite) NSString *deviceModel;
// 设备标识
@property (nonatomic, copy, readwrite) NSString *UDID;
@end
@implementation HLNetworkLoggerConfig
+ (instancetype)config {
return [[self alloc] init];
}
- (instancetype)init {
self = [super init];
if (self) {
_channelID = @"";
_appKey = @"";
_appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] ?: @"";
_appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: @"";
_serviceType = @"";
_enableLocalLog = NO;
_loggerLevel = HLNetworkLoggerNoneLevel;
_logAutoSaveCount = 50;
_loggerType = HLNetworkLoggerTypeJSON;
}
return self;
}
- (NSString *)logFilePath {
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"com.qkhl.HLNetworking/log"];
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:nil]) {
[[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
}
NSDateFormatter *myFormatter = [[NSDateFormatter alloc] init];
[myFormatter setDateFormat:@"yyyy-MM-dd_HH-mm-ss"];
NSString *dateString = [myFormatter stringFromDate:[NSDate date]];
return [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.log", dateString]];
}
@end
================================================
FILE: HLNetworking/Source/Logger/NSNull+ToDictionary.h
================================================
//
// NSNull+ToDictionary.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSNull (ToDictionary)
- (NSDictionary *)toDictionary;
@end
================================================
FILE: HLNetworking/Source/Logger/NSNull+ToDictionary.m
================================================
//
// NSNull+ToDictionary.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "NSNull+ToDictionary.h"
@implementation NSNull (ToDictionary)
- (NSDictionary *)toDictionary {
return @{@"NSNull": @"null"};
}
@end
================================================
FILE: HLNetworking/Source/Logger/UIDevice+deviceInfo.h
================================================
//
// UIDevice+deviceInfo.h
// HLNetworking
//
// Created by Georg Kitz on 20.08.11.
// Copyright 2011 Aurora Apps. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIDevice (deviceInfo)
- (NSString *) hl_uuid;
- (NSString *) hl_udid;
- (NSString *) hl_macaddress;
- (NSString *) hl_macaddressMD5;
- (NSString *) hl_machineType;
@end
================================================
FILE: HLNetworking/Source/Logger/UIDevice+deviceInfo.m
================================================
//
// UIDevice+deviceInfo.m
// HLNetworking
//
// Created by Georg Kitz on 20.08.11.
// Copyright 2011 Aurora Apps. All rights reserved.
//
#import "UIDevice+deviceInfo.h"
#include <CommonCrypto/CommonDigest.h>
#include <sys/socket.h> // Per msqr
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include <net/if.h>
#include <net/if_dl.h>
static NSString *HLKeychainServiceName = @"HLKeychainServiceName";
static NSString *HLUDIDName = @"HLNetworkingUDID";
static NSString *HLPasteboardType = @"HLPasteboardType";
@interface UIDevice(Private)
- (NSString *) localMAC;
@end
@implementation UIDevice (deviceInfo)
///////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Private Methods
// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
- (NSString *) localMAC{
int mib[6];
size_t len;
char *buf;
unsigned char *ptr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
if ((mib[5] = if_nametoindex("en0")) == 0) {
printf("Error: if_nametoindex error\n");
return NULL;
}
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
printf("Error: sysctl, take 1\n");
return NULL;
}
if ((buf = malloc(len)) == NULL) {
printf("Could not allocate memory. error!\n");
return NULL;
}
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
printf("Error: sysctl, take 2");
free(buf);
return NULL;
}
ifm = (struct if_msghdr *)buf;
sdl = (struct sockaddr_dl *)(ifm + 1);
ptr = (unsigned char *)LLADDR(sdl);
NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
*ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
free(buf);
return outstring;
}
////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Public Methods
- (NSString *)hl_createUUID {
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);
return (__bridge_transfer NSString *)string;
}
- (NSString *)hl_uuid {
NSString *key = @"HLNetworkingUUID";
NSString *uuid = [[NSUserDefaults standardUserDefaults] objectForKey:key];
if (uuid.length == 0) {
[[NSUserDefaults standardUserDefaults] setObject:[self hl_createUUID] forKey:key];
return [[[NSUserDefaults standardUserDefaults] objectForKey:key] copy];
} else {
return uuid;
}
}
- (NSString *) hl_udid {
NSString *udid = [self getUDID];
if (udid.length==0) {
udid = [self hl_uuid];
[self saveUDID:udid];
}
return udid;
}
- (NSString *)hl_macaddress {
NSString *key = @"macAddress";
NSString *macAddress = [[NSUserDefaults standardUserDefaults] objectForKey:key];
if (macAddress.length == 0) {
macAddress = [self localMAC];
if (macAddress.length>0){
[[NSUserDefaults standardUserDefaults] setObject:macAddress forKey:key];
[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"macaddressMD5"];
}
}
return macAddress;
}
- (NSString *) hl_macaddressMD5 {
NSString *key = @"MACAddressMD5";
NSString *macid = [[NSUserDefaults standardUserDefaults] objectForKey:key];
if (macid.length == 0) {
NSString *macaddress = [[UIDevice currentDevice] hl_macaddress];
macid = [self md5:macaddress];
if (!macid){
macid = @"macaddress_empty";
}else{
[[NSUserDefaults standardUserDefaults] setObject:macid forKey:key];
}
}
return macid;
}
- (NSString *)hl_machineType {
struct utsname systemInfo;
uname(&systemInfo);
NSString *machineType = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"iPhoneTypeDefine" ofType:@"plist"];
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSString *type = dictionary[machineType];
if (type) {
return type;
} else {
return machineType;
}
}
#pragma mark - UDID相关
- (NSString *)getUDID {
NSData *udidData = [self searchKeychainCopyMatching:HLUDIDName];
NSString *udid = nil;
if (udidData != nil) {
NSString *temp = [[NSString alloc] initWithData:udidData encoding:NSUTF8StringEncoding];
udid = [NSString stringWithFormat:@"%@", temp];
}
if (udid.length == 0) {
udid = [self readPasteBoradforIdentifier:HLUDIDName];
}
return udid;
}
#pragma mark - UDID相关
- (void)saveUDID:(NSString *)udid {
BOOL saveOk = NO;
NSData *udidData = [self searchKeychainCopyMatching:HLUDIDName];
if (udidData == nil) {
saveOk = [self createKeychainValue:udid forIdentifier:HLUDIDName];
} else {
saveOk = [self updateKeychainValue:udid forIdentifier:HLUDIDName];
}
if (!saveOk) {
[self createPasteBoradValue:udid forIdentifier:HLUDIDName];
}
}
- (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];
[searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding];
[searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric];
[searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount];
[searchDictionary setObject:HLKeychainServiceName forKey:(__bridge id)kSecAttrService];
return searchDictionary;
}
- (NSData *)searchKeychainCopyMatching:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
// Add search attributes
[searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
// Add search return types
[searchDictionary setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
CFDataRef result = nil;
SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary,
(CFTypeRef *)&result);
return (__bridge NSData *)result;
}
- (BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier {
NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];
NSData *passwordData = [value dataUsingEncoding:NSUTF8StringEncoding];
[dictionary setObject:passwordData forKey:(__bridge id)kSecValueData];
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL);
if (status == errSecSuccess) {
return YES;
}
return NO;
}
- (BOOL)updateKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
NSData *passwordData = [value dataUsingEncoding:NSUTF8StringEncoding];
[updateDictionary setObject:passwordData forKey:(__bridge id)kSecValueData];
OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)searchDictionary,
(__bridge CFDictionaryRef)updateDictionary);
if (status == errSecSuccess) {
return YES;
}
return NO;
}
- (void)deleteKeychainValue:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
SecItemDelete((__bridge CFDictionaryRef)searchDictionary);
}
- (void)createPasteBoradValue:(NSString *)value forIdentifier:(NSString *)identifier {
UIPasteboard *pb = [UIPasteboard pasteboardWithName:HLKeychainServiceName create:YES];
NSDictionary *dict = [NSDictionary dictionaryWithObject:value forKey:identifier];
NSData *dictData = [NSKeyedArchiver archivedDataWithRootObject:dict];
[pb setData:dictData forPasteboardType:HLPasteboardType];
}
- (NSString *)readPasteBoradforIdentifier:(NSString *)identifier {
UIPasteboard *pb = [UIPasteboard pasteboardWithName:HLKeychainServiceName create:YES];
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:[pb dataForPasteboardType:HLPasteboardType]];
return [dict objectForKey:identifier];
}
- (NSString *)md5:(NSString *)string {
NSData* inputData = [string dataUsingEncoding:NSUTF8StringEncoding];
unsigned char outputData[CC_MD5_DIGEST_LENGTH];
CC_MD5([inputData bytes], (unsigned int)[inputData length], outputData);
NSMutableString* hashStr = [NSMutableString string];
int i = 0;
for (i = 0; i < CC_MD5_DIGEST_LENGTH; ++i)
[hashStr appendFormat:@"%02x", outputData[i]];
return hashStr;
}
@end
================================================
FILE: HLNetworking/Source/Logger/iPhoneTypeDefine.plist
================================================
<?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>i386</key>
<string>32-bit Simulator</string>
<key>x86_64</key>
<string>64-bit Simulator</string>
<key>iPod1,1</key>
<string>iPod Touch</string>
<key>iPod2,1</key>
<string>iPod Touch 2</string>
<key>iPod3,1</key>
<string>iPod Touch 3</string>
<key>iPod4,1</key>
<string>iPod Touch 4</string>
<key>iPod5,1</key>
<string>iPod Touch 5</string>
<key>iPod7,1</key>
<string>iPod Touch 6</string>
<key>iPad1,1</key>
<string>iPad</string>
<key>iPad2,1</key>
<string>iPad 2</string>
<key>iPad2,2</key>
<string>iPad 2</string>
<key>iPad2,3</key>
<string>iPad 2</string>
<key>iPad2,4</key>
<string>iPad 2</string>
<key>iPad2,5</key>
<string>iPad Mini</string>
<key>iPad2,6</key>
<string>iPad Mini</string>
<key>iPad2,7</key>
<string>iPad Mini</string>
<key>iPad3,1</key>
<string>iPad 3</string>
<key>iPad3,2</key>
<string>iPad 3</string>
<key>iPad3,3</key>
<string>iPad 3</string>
<key>iPad3,4</key>
<string>iPad 4</string>
<key>iPad3,5</key>
<string>iPad 4</string>
<key>iPad3,6</key>
<string>iPad 4</string>
<key>iPad4,1</key>
<string>iPad Air</string>
<key>iPad4,2</key>
<string>iPad Air</string>
<key>iPad4,3</key>
<string>iPad Air</string>
<key>iPad4,4</key>
<string>iPad Mini 2</string>
<key>iPad4,5</key>
<string>iPad Mini 2</string>
<key>iPad4,6</key>
<string>iPad Mini 2</string>
<key>iPad4,7</key>
<string>iPad Mini 3</string>
<key>iPad4,8</key>
<string>iPad Mini 3</string>
<key>iPad4,9</key>
<string>iPad Mini 3</string>
<key>iPad5,1</key>
<string>iPad Mini 4</string>
<key>iPad5,2</key>
<string>iPad Mini 4</string>
<key>iPad5,3</key>
<string>iPad Air 2</string>
<key>iPad5,4</key>
<string>iPad Air 2</string>
<key>iPad6,3</key>
<string>iPad Pro 9.7</string>
<key>iPad6,4</key>
<string>iPad Pro 9.7</string>
<key>iPad6,7</key>
<string>iPad Pro 12.9</string>
<key>iPad6,8</key>
<string>iPad Pro 12.9</string>
<key>iPhone1,1</key>
<string>iPhone</string>
<key>iPhone1,2</key>
<string>iPhone 3G</string>
<key>iPhone2,1</key>
<string>iPhone 3GS</string>
<key>iPhone3,1</key>
<string>iPhone 4 (GSM)</string>
<key>iPhone3,3</key>
<string>iPhone 4 (CDMA/Verizon/Sprint)</string>
<key>iPhone4,1</key>
<string>iPhone 4S</string>
<key>iPhone5,1</key>
<string>iPhone 5 (model A1428, AT&T/Canada)</string>
<key>iPhone5,2</key>
<string>iPhone 5 (model A1429, everything else)</string>
<key>iPhone5,3</key>
<string>iPhone 5c (model A1456, A1532 | GSM)</string>
<key>iPhone5,4</key>
<string>iPhone 5c (model A1507, A1516, A1526 (China), A1529 | Global)</string>
<key>iPhone6,1</key>
<string>iPhone 5s (model A1433, A1533 | GSM)</string>
<key>iPhone6,2</key>
<string>iPhone 5s (model A1457, A1518, A1528 (China), A1530 | Global)</string>
<key>iPhone7,1</key>
<string>iPhone 6 Plus</string>
<key>iPhone7,2</key>
<string>iPhone 6</string>
<key>iPhone8,1</key>
<string>iPhone 6s</string>
<key>iPhone8,2</key>
<string>iPhone 6s Plus</string>
<key>iPhone8,4</key>
<string>iPhone SE</string>
<key>iPhone9,1</key>
<string>iPhone 7</string>
<key>iPhone9,2</key>
<string>iPhone 7 Plus</string>
<key>iPhone9,3</key>
<string>iPhone 7</string>
<key>iPhone9,4</key>
<string>iPhone 7 Plus</string>
</dict>
</plist>
================================================
FILE: HLNetworking/Source/Manager/HLNetworkManager.h
================================================
//
// HLNetworkManager.h
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "HLNetworkConst.h"
@class HLNetworkConfig;
@class HLURLRequest;
@class HLRequestGroup;
@protocol HLNetworkResponseDelegate;
// 判断当前是否为审核版本
FOUNDATION_EXPORT inline BOOL HLJudgeVersion(void);
// 设置是否为审核版本
FOUNDATION_EXPORT inline void HLJudgeVersionSwitch(BOOL isR);
NS_ASSUME_NONNULL_BEGIN
@interface HLNetworkManager : NSObject
#pragma mark - property
@property (nonatomic, strong, readonly) HLNetworkConfig *config;
+ (HLNetworkConfig *)config;
#pragma mark - initialize method
// 请使用manager或sharedManager
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
// 返回一个新的manager对象
+ (instancetype)manager;
// 返回单例
+ (instancetype)sharedManager;
// 配置设置
+ (void)setupConfig:(void(^)(HLNetworkConfig *config))configBlock;
- (void)setupConfig:(void(^)(HLNetworkConfig *config))configBlock;
#pragma mark - process
// 发送API请求,默认为manager内置队列
+ (void)send:(__kindof HLURLRequest *)request;
- (void)send:(__kindof HLURLRequest *)request;
// 发送一组请求
+ (void)sendGroup:(HLRequestGroup *)group;
- (void)sendGroup:(HLRequestGroup *)group;
// 取消API请求,如果该请求已经发送或者正在发送,则不保证一定可以取消,但会将Block回落点置空,delegate正常回调,默认为manager内置队列
+ (void)cancel:(__kindof HLURLRequest *)request;
- (void)cancel:(__kindof HLURLRequest *)request;
// 取消API请求,如果该请求已经发送或者正在发送,则不保证一定可以取消,但会将Block回落点置空,delegate正常回调,默认为manager内置队列
+ (void)cancelGroup:(HLRequestGroup *)group;
- (void)cancelGroup:(HLRequestGroup *)group;
// 恢复Task
+ (void)resume:(__kindof HLURLRequest *)request;
- (void)resume:(__kindof HLURLRequest *)request;
// 暂停Task
+ (void)pause:(__kindof HLURLRequest *)request;
- (void)pause:(__kindof HLURLRequest *)request;
// 注册网络请求监听者
+ (void)registerResponseObserver:(id<HLNetworkResponseDelegate>)observer;
- (void)registerResponseObserver:(id<HLNetworkResponseDelegate>)observer;
// 删除网络请求监听者
+ (void)removeResponseObserver:(id<HLNetworkResponseDelegate>)observer;
- (void)removeResponseObserver:(id<HLNetworkResponseDelegate>)observer;
#pragma mark - reachability相关
// 当前reachability状态
@property (nonatomic, assign, readonly) HLReachabilityStatus reachabilityStatus;
// 当前是否可访问网络
@property (nonatomic, assign, readonly, getter = isReachable) BOOL reachable;
// 当前是否使用数据流量访问网络
@property (nonatomic, assign, readonly, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
// 当前是否使用WiFi访问网络
@property (nonatomic, assign, readonly, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
// 通过sharedMager单例,获取当前reachability状态
+ (HLReachabilityStatus)reachabilityStatus;
// 通过sharedMager单例,获取当前是否可访问网络
+ (BOOL)isReachable;
// 通过sharedMager单例,获取当前是否使用数据流量访问网络
+ (BOOL)isReachableViaWWAN;
// 通过sharedMager单例,获取当前是否使用WiFi访问网络
+ (BOOL)isReachableViaWiFi;
// 开启默认reachability监视器,block返回状态
+ (void)listening:(HLReachabilityBlock)listener;
// 默认reachability监视器停止监听
+ (void)stopListening;
// 监听给定的域名是否可以访问,block内返回状态
- (void)listeningWithDomain:(NSString *)domain listeningBlock:(HLReachabilityBlock)listener;
// 停止给定域名的网络状态监听
- (void)stopListeningWithDomain:(NSString *)domain;
@end
#pragma mark - manager监听代理
@protocol HLNetworkResponseDelegate <NSObject>
// 快速设置需要监听的task对象
#define HLObserverRequests(...) \
- (NSArray <__kindof HLURLRequest *>* _Nonnull)observerRequests { \
return [NSArray arrayWithObjects:__VA_ARGS__, nil]; \
}
@required
// 设置需要监听的task对象
- (NSArray <__kindof HLURLRequest *>*)observerRequests;
@optional
// task 上传、下载等长时间执行的Progress进度
- (void)requestProgress:(nullable NSProgress *)progress atRequest:(nullable __kindof HLURLRequest *)request;
// 请求成功的回调
- (void)requestSucess:(nullable id)responseObject atRequest:(nullable __kindof HLURLRequest *)request;
// 请求失败的回调
- (void)requestFailure:(nullable NSError *)error atRequest:(nullable __kindof HLURLRequest *)request;
@end
NS_ASSUME_NONNULL_END
================================================
FILE: HLNetworking/Source/Manager/HLNetworkManager.m
================================================
//
// HLNetworkManager.m
// HLNetworking
//
// Created by wangshiyu13 on 2017/1/23.
// Copyright © 2017年 wangshiyu13. All rights reserved.
//
#import "HLNetworkManager.h"
#import "HLNetworkEngine.h"
#import "HLNetworkConfig.h"
#import "HLNetworkMacro.h"
#import "HLNetworkLogger.h"
#import "HLDebugMessage.h"
#import "HLURLRequest_InternalParams.h"
#import "HLRequestGroup.h"
#import "HLTaskRequest.h"
#import "HLAPIRequest_InternalParams.h"
inline BOOL HLJudgeVersion(void) { return [[NSUserDefaults standardUserDefaults] boolForKey:@"isR"]; }
inline void HLJudgeVersionSwitch(BOOL isR) { [[NSUserDefaults standardUserDefaults] setBool:isR forKey:@"isR"]; }
// 创建任务队列
static dispatch_queue_t qkhl_network_request_queue() {
static dispatch_queue_t qkhl_network_request_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
qkhl_network_request_queue =
dispatch_queue_create("com.qkhl.wangshiyu13.networking.callback.queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
});
return qkhl_network_request_queue;
}
// 创建上传下载任务队列
static dispatch_queue_t qkhl_network_task_queue() {
static dispatch_queue_t qkhl_network_task_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
qkhl_network_task_queue =
dispatch_queue_create("com.qkhl.wangshiyu13.networking.task.queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
});
return qkhl_network_task_queue;
}
@interface HLNetworkManager () {
dispatch_semaphore_t _lock;
}
@property (nonatomic, strong, readwrite) HLNetworkConfig *config;
@property (nonatomic, strong) NSHashTable<id <HLNetworkResponseDelegate>> *responseObservers;
@property (nonatomic, assign, readwrite) HLReachabilityStatus reachabilityStatus;
@property (nonatomic, assign, readwrite, getter = isReachable) BOOL reachable;
@property (nonatomic, assign, readwrite, getter = isReachableViaWWAN) BOOL reachableViaWWAN;
@property (nonatomic, assign, readwrite, getter = isReachableViaWiFi) BOOL reachableViaWiFi;
@end
@implementation HLNetworkManager
+ (HLNetworkConfig *)config {
return [[self sharedManager] config];
}
#pragma mark - initialize method
+ (instancetype)manager {
return [[self alloc] init];
}
+ (instancetype)sharedManager {
static HLNetworkManager *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}
- (instancetype)init {
self = [super init];
if (self) {
_lock = dispatch_semaphore_create(1);
_config = [HLNetworkConfig config];
_reachabilityStatus = HLReachabilityStatusUnknown;
_responseObservers = [NSHashTable hashTableWithOptions:NSHashTableWeakMemory];
}
return self;
}
- (void)setupConfig:(void (^)(HLNetworkConfig * _Nonnull config))configBlock {
HL_SAFE_BLOCK(configBlock, self.config);
}
+ (void)setupConfig:(void (^)(HLNetworkConfig * _Nonnull config))configBlock {
[[self sharedManager] setupConfig:configBlock];
}
#pragma mark - process
// 发送API请求,默认为manager内置队列
- (void)send:(__kindof HLURLRequest *)request {
@hl_weakify(self);
if (!request.queue) {
if ([request isKindOfClass:[HLTaskRequest class]]) {
request.queue = qkhl_network_task_queue();
} else {
request.queue = qkhl_network_request_queue();
}
}
dispatch_async(request.queue, ^{
@hl_strongify(self);
[self send:request atSemaphore:nil atGroup:nil];
});
}
+ (void)send:(__kindof HLURLRequest *)request {
[[self sharedManager] send:request];
}
// 发送一组请求,使用信号量做同步请求,使用group做完成通知
- (void)sendGroup:(HLRequestGroup *)group {
if (!group) return;
dispatch_queue_t queue;
if (group.customQueue) {
queue = group.customQueue;
} else {
if ([group[0] isKindOfClass:[HLTaskRequest class]]) {
queue = qkhl_network_task_queue();
} else {
queue = qkhl_network_request_queue();
}
}
// 根据groupMode 配置信号量
dispatch_semaphore_t semaphore = nil;
if (group.groupMode == HLRequestGroupModeChain) {
semaphore = dispatch_semaphore_create(group.maxRequestCount);
}
dispatch_group_t api_group = dispatch_group_create();
@hl_weakify(self);
dispatch_async(queue, ^{
[group enumerateObjectsUsingBlock:^(HLURLRequest * _Nonnull request, NSUInteger idx, BOOL * _Nonnull stop) {
@hl_strongify(self);
request.queue = queue;
if (group.groupMode == HLRequestGroupModeChain) {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
dispatch_group_enter(api_group);
[self send:request atSemaphore:semaphore atGroup:api_group];
}];
dispatch_group_notify(api_group, dispatch_get_main_queue(), ^{
if (group.delegate) {
[group.delegate requestGroupAllDidFinished:group];
}
});
});
}
+ (void)sendGroup:(HLRequestGroup *)group {
[[self sharedManager] sendGroup:group];
}
// 取消API请求,如果该请求已经发送或者正在发送,则不保证一定可以取消,但会将Block回落点置空,delegate正常回调,默认为manager内置队列
- (void)cancel:(__kindof HLURLRequest *)request {
if (!request.queue) {
if ([request isKindOfClass:[HLTaskRequest class]]) {
request.queue = qkhl_network_task_queue();
} else {
request.queue = qkhl_network_request_queue();
}
}
dispatch_async(request.queue, ^{
[[HLNetworkEngine sharedEngine] cancelRequestByIdentifier:request.hashKey];
});
}
+ (void)cancel:(__kindof HLURLRequest *)request {
[[self sharedManager] cancel:request];
}
// 取消API请求,如果该请求已经发送或者正在发送,则不保证一定可以取消,但会将Block回落点置空,delegate正常回调,默认为manager内置队列
- (void)cancelGroup:(HLRequestGroup *)group {
NSAssert(group.count != 0, @"APIGroup元素不可小于1");
[group enumerateObjectsUsingBlock:^(__kindof HLURLRequest * _Nonnull request, NSUInteger idx, BOOL * _Nonnull stop) {
[self cancel:request];
}];
}
+ (void)cancelGroup:(HLRequestGroup *)group {
[[self sharedManager] cancelGroup:group];
}
// 恢复Task
- (void)resume:(__kindof HLURLRequest *)request {
@hl_weakify(self);
if (!request.queue) {
if ([request isKindOfClass:[HLTaskRequest class]]) {
request.queue = qkhl_network_task_queue();
} else {
request.queue = qkhl_network_request_queue();
}
}
dispatch_async(request.queue, ^{
@hl_strongify(self);
NSURLSessionTask *sessionTask = [[HLNetworkEngine sharedEngine] requestByIdentifier:request.hashKey];
if (sessionTask) {
[sessionTask resume];
} else {
[self send:request];
}
});
}
+ (void)resume:(__kindof HLURLRequest *)request {
[[self sharedManager] resume:request];
}
// 暂停Task
- (void)pause:(__kindof HLURLRequest *)request {
if (!request.queue) {
if ([request isKindOfClass:[HLTaskRequest class]]) {
request.queue = qkhl_network_task_queue();
} else {
request.queue = qkhl_network_request_queue();
}
}
dispatch_async(request.queue, ^{
NSURLSessionTask *sessionTask = [[HLNetworkEngine sharedEngine] requestByIdentifier:request.hashKey];
if (sessionTask) {
[sessionTask suspend];
}
});
}
+ (void)pause:(__kindof HLURLRequest *)request {
[[self sharedManager] pause:request];
}
// 注册网络请求监听者
- (void)registerResponseObserver:(id<HLNetworkResponseDelegate>)observer {
HLLock();
[self.responseObservers addObject:observer];
HLUnlock();
}
+ (void)registerResponseObserver:(id<HLNetworkResponseDelegate>)observer {
[[self sharedManager] registerResponseObserver:observer];
}
// 删除网络请求监听者
- (void)removeResponseObserver:(id<HLNetworkResponseDelegate>)observer {
HLLock();
if ([self.responseObservers containsObject:observer]) {
[self.responseObservers removeObject:observer];
}
HLUnlock();
}
+ (void)removeResponseObserver:(id<HLNetworkResponseDelegate>)observer {
[[self sharedManager] removeResponseObserver:observer];
}
#pragma mark - reachability
- (BOOL)isReachable {
return [self isReachableViaWWAN] || [self isReachableViaWiFi];
}
- (BOOL)isReachableViaWWAN {
return self.reachabilityStatus == HLReachabilityStatusReachableViaWWAN;
}
- (BOOL)isReachableViaWiFi {
return self.reachabilityStatus == HLReachabilityStatusReachableViaWiFi;
}
+ (HLReachabilityStatus)reachabilityStatus {
return [[self sharedManager] reachabilityStatus];
}
+ (BOOL)isReachable {
return [[self sharedManager] isReachable];
}
+ (BOOL)isReachableViaWWAN {
return [[self sharedManager] isReachableViaWWAN];
}
+ (BOOL)isReachableViaWiFi {
return [[self sharedManager] isReachableViaWiFi];
}
+ (void)listening:(HLReachabilityBlock)listener {
[[self sharedManager] listeningWithDomain:[[self sharedManager] config].request.baseURL listeningBlock:listener];
}
+ (void)stopListening {
[[self sharedManager] stopListeningWithDomain:[[self sharedManager] config].request.baseURL];
}
- (void)listeningWithDomain:(NSString *)domain listeningBlock:(HLReachabilityBlock)listener {
if (self.config.enableReachability) {
@hl_weakify(self)
[[HLNetworkEngine sharedEngine] listeningWithDomain:domain listeningBlock:^(HLReachabilityStatus status) {
@hl_strongify(self)
self.reachabilityStatus = status;
listener(status);
}];
}
}
- (void)stopListeningWithDomain:(NSString *)domain {
[[HLNetworkEngine sharedEngine] stopListeningWithDomain:domain];
}
#pragma mark - private method
- (void)send:(HLURLRequest *)request
atSemaphore:(dispatch_semaphore_t)semaphore
atGroup:(dispatch_group_t)group {
// 对api.delegate 发送即将请求api的消息
if ([request.delegate respondsToSelector:@selector(requestWillBeSent:)]) {
dispatch_async_main(self.config.request.callbackQueue, ^{
[request.delegate requestWillBeSent:request];
});
}
if (self.config.tips.isNetworkingActivityIndicatorEnabled) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
// 定义进度block
@hl_weakify(self)
void (^progressBlock)(NSProgress *proc) = ^(NSProgress *proc) {
if (proc.totalUnitCount <= 0) return;
dispatch_async_main(self.config.request.callbackQueue, ^{
for (id<HLNetworkResponseDelegate> obj in self.responseObservers) {
if ([[obj observerRequests] containsObject:request]) {
if ([obj respondsToSelector:@selector(requestProgress:atRequest:)]) {
[obj requestProgress:proc atRequest:request];
}
}
}
});
};
// 定义回调block
void (^callBackBlock)(HLURLRequest *request, id responseObject, NSError *error)
= ^(HLURLRequest *request, id responseObject, NSError *error) {
@hl_strongify(self)
if (self.config.tips.isNetworkingActivityIndicatorEnabled) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
[self callbackWithRequest:request
andResultObject:responseObject
andError:error
andGroup:group
andSemaphore:semaphore];
};
[[HLNetworkEngine sharedEngine] sendRequest:request
andConfig:self.config
progressBack:progressBlock
callBack:callBackBlock];
// 对api.delegate 发送已经请求api的消息
if ([request.delegate respondsToSelector:@selector(requestDidSent:)]) {
dispatch_async_main(self.config.request.callbackQueue, ^{
[request.delegate requestDidSent:request];
});
}
}
/**
Task完成的回调方法
@param request 调用的request
@param resultObject 返回的对象
@param error 返回的错误
@param group 调用的组
@param semaphore 调用的信号量
*/
- (void)callbackWithRequest:(HLURLRequest *)request
andResultObject:(id)resultObject
andError:(NSError *)error
andGroup:(dispatch_group_t)group
andSemaphore:(dispatch_semaphore_t)semaphore {
// 处理回调的block
NSError *netError = error;
if (netError) {
// 网络状态不好时自动重试
if (request.retryCount > 0) {
request.retryCount --;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self send:request atSemaphore:semaphore atGroup:group];
});
return;
}
// 如果不是reachability无法访问host或用户取消错误(NSURLErrorCancelled),则对错误提示进行处理
if (![error.domain isEqualToString: NSURLErrorDomain] &&
error.code != NSURLErrorCancelled) {
// 使用KVC修改error内部属性
// 默认使用self.config.generalErrorTypeStr = "服务器连接错误,请稍候重试"
NSMutableDictionary *tmpUserInfo = [[NSMutableDictionary alloc]initWithDictionary:error.userInfo copyItems:NO];
if (![[tmpUserInfo allKeys] containsObject:NSLocalizedFailureReasonErrorKey]) {
tmpUserInfo[NSLocalizedFailureReasonErrorKey] = NSLocalizedString(self.config.tips.generalErrorTypeStr, nil);
}
if (![[tmpUserInfo allKeys] containsObject:NSLocalizedRecoverySuggestionErrorKey]) {
tmpUserInfo[NSLocalizedRecoverySuggestionErrorKey] = NSLocalizedString(self.config.tips.generalErrorTypeStr, nil);
}
// 加上 networking error code
NSString *newErrorDescription = self.config.tips.generalErrorTypeStr;
if (self.config.policy.isErrorCodeDisplayEnabled) {
newErrorDescription = [NSString stringWithFormat:@"%@, error code = (%ld)", self.config.tips.generalErrorTypeStr, (long)error.code];
}
tmpUserInfo[NSLocalizedDescriptionKey] = NSLocalizedString(newErrorDescription, nil);
NSDictionary *userInfo = [tmpUserInfo copy];
netError = [NSError errorWithDomain:error.domain
code:error.code
userInfo:userInfo];
}
}
if ([request isKindOfClass:[HLAPIRequest class]]) {
HLAPIRequest *tmpRequest = (HLAPIRequest *)request;
if (tmpRequest.objReformerDelegate) {
resultObject = [tmpRequest.objReformerDelegate reformerObject:resultObject andError:netError atRequest:tmpRequest];
}
}
// 设置Debug及log信息
HLDebugMessage *msg = [[HLDebugMessage alloc] initWithRequest:request
andResult:resultObject
andError:netError
andQueueName:[NSString stringWithFormat:@"%@", [request isKindOfClass:[HLTaskRequest class]] ? qkhl_network_task_queue() : qkhl_network_request_queue()]];
#if DEBUG
if (self.config.enableGlobalLog) {
[HLNetworkLogger logInfoWithDebugMessage:msg];
}
if (request.debugHandler) {
request.debugHandler(msg);
request.debugHandler = nil;
}
#endif
if ([HLNetworkLogger isEnable]) {
NSDictionary *msgDictionary;
if ([HLNetworkLogger currentDelegate]) {
msgDictionary = [[HLNetworkLogger currentDelegate] customInfoWithMessage:msg];
} else {
msgDictionary = [msg toDictionary];
}
[HLNetworkLogger addLogInfoWithDictionary:msgDictionary];
}
if (netError) {
if ([request failureHandler]) {
dispatch_async_main(self.config.request.callbackQueue, ^{
request.failureHandler(netError);
request.failureHandler = nil;
});
}
} else {
if ([request successHandler]) {
dispatch_async_main(self.config.request.callbackQueue, ^{
request.successHandler(resultObject);
request.successHandler = nil;
});
}
}
if (request.progressHandler) {
request.progressHandler = nil;
}
// 处理回调的delegate
for (id<HLNetworkResponseDelegate> observer in self.responseObservers) {
if ([[observer observerRequests] containsObject:request]) {
if (netError) {
if ([observer respondsToSelector:@selector(requestFailure:atRequest:)]) {
dispatch_async_main(self.config.request.callbackQueue, ^{
[observer requestFailure:netError atRequest:request];
});
}
} else {
if ([observer respondsToSelector:@selector(requestSucess:atRequest:)]) {
dispatch_async_main(self.config.request.callbackQueue, ^{
[observer requestSucess:resultObject atRequest:request];
});
}
}
}
}
// 完成后离组
if (group) {
dispatch_group_leave(group);
}
// 完成后信号量加1
if (semaphore) {
dispatch_semaphore_signal(semaphore);
}
}
//获取已下载的文件大小
- (unsigned long long)fileSizeForPath:(NSString *)path {
signed long long fileSize = 0;
NSFileManager *fileManager = [NSFileManager new]; // default is not thread safe
if ([fileManager fileExistsAtPath:path]) {
NSError *error = nil;
NSDictionary *fileDict = [fileManager attributesOfItemAtPath:path error:&error];
if (!error && fileDict) {
fileSize = [fileDict fileSize];
}
}
return fileSize;
}
@end
================================================
FILE: HLNetworking/ViewController.h
================================================
//
// ViewController.h
// HLNetworking
//
// Created by wangshiyu13 on 2016/9/22.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
================================================
FILE: HLNetworking/ViewController.m
================================================
//
// ViewController.m
// HLNetworking
//
// Created by wangshiyu13 on 2016/9/22.
// Copyright © 2016年 wangshiyu13. All rights reserved.
//
#import "ViewController.h"
#import
gitextract_diowpqpv/ ├── .gitignore ├── HLNetworking/ │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets/ │ │ └── AppIcon.appiconset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── HLAPICenter+home.h │ ├── HLAPICenter+home.m │ ├── Info.plist │ ├── Source/ │ │ ├── Center/ │ │ │ ├── HLAPICenter.h │ │ │ ├── HLAPICenter.m │ │ │ ├── HLAPIMacro.h │ │ │ ├── HLBaseObjReformer.h │ │ │ └── HLBaseObjReformer.m │ │ ├── Config/ │ │ │ ├── HLFormDataConfig.h │ │ │ ├── HLFormDataConfig.m │ │ │ ├── HLNetworkConfig.h │ │ │ ├── HLNetworkConfig.m │ │ │ ├── HLNetworkConst.h │ │ │ ├── HLNetworkMacro.h │ │ │ ├── HLNetworkPolicyConfig.h │ │ │ ├── HLNetworkPolicyConfig.m │ │ │ ├── HLNetworkRequestConfig.h │ │ │ ├── HLNetworkRequestConfig.m │ │ │ ├── HLNetworkTipsConfig.h │ │ │ ├── HLNetworkTipsConfig.m │ │ │ ├── HLSecurityPolicyConfig.h │ │ │ └── HLSecurityPolicyConfig.m │ │ ├── Engine/ │ │ │ ├── HLNetworkEngine.h │ │ │ └── HLNetworkEngine.m │ │ ├── Generator/ │ │ │ ├── Request/ │ │ │ │ ├── API/ │ │ │ │ │ ├── HLAPIRequest.h │ │ │ │ │ ├── HLAPIRequest.m │ │ │ │ │ └── HLAPIRequest_InternalParams.h │ │ │ │ ├── Base/ │ │ │ │ │ ├── HLURLRequest.h │ │ │ │ │ ├── HLURLRequest.m │ │ │ │ │ └── HLURLRequest_InternalParams.h │ │ │ │ ├── Group/ │ │ │ │ │ ├── HLRequestGroup.h │ │ │ │ │ └── HLRequestGroup.m │ │ │ │ └── Task/ │ │ │ │ ├── HLTaskRequest.h │ │ │ │ ├── HLTaskRequest.m │ │ │ │ └── HLTaskRequest_InternalParams.h │ │ │ ├── Response/ │ │ │ │ ├── HLURLResponse.h │ │ │ │ └── HLURLResponse.m │ │ │ └── Result/ │ │ │ ├── HLURLResult.h │ │ │ └── HLURLResult.m │ │ ├── HLNetworking.h │ │ ├── Logger/ │ │ │ ├── HLDebugMessage.h │ │ │ ├── HLDebugMessage.m │ │ │ ├── HLNetworkLogger.h │ │ │ ├── HLNetworkLogger.m │ │ │ ├── HLNetworkLoggerConfig.h │ │ │ ├── HLNetworkLoggerConfig.m │ │ │ ├── NSNull+ToDictionary.h │ │ │ ├── NSNull+ToDictionary.m │ │ │ ├── UIDevice+deviceInfo.h │ │ │ ├── UIDevice+deviceInfo.m │ │ │ └── iPhoneTypeDefine.plist │ │ └── Manager/ │ │ ├── HLNetworkManager.h │ │ └── HLNetworkManager.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── HLNetworking.podspec ├── HLNetworking.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── HLNetworking.xcscheme ├── HLNetworkingTests/ │ ├── HLAPIRequestTest.m │ ├── HLManagerTests.m │ ├── HLRequestGroupTests.m │ ├── HLTaskRequestTest.m │ ├── HLTestCase.h │ ├── HLTestCase.m │ ├── Info.plist │ └── httpbin.org.cer ├── LICENSE ├── Podfile ├── README.md └── README_old.md
SYMBOL INDEX (7 symbols across 7 files)
FILE: HLNetworking/Source/Config/HLNetworkConst.h
type HLReachabilityStatusUnknown (line 53) | typedef NS_ENUM(NSUInteger, HLReachabilityStatus) {
FILE: HLNetworking/Source/Config/HLNetworkMacro.h
function BOOL (line 12) | static inline BOOL IsEmptyValue(id thing) {
FILE: HLNetworking/Source/Config/HLSecurityPolicyConfig.h
type HLSSLPinningModeNone (line 12) | typedef NS_ENUM(NSUInteger, HLSSLPinningMode) {
FILE: HLNetworking/Source/Generator/Request/Group/HLRequestGroup.h
type HLRequestGroupModeBatch (line 14) | typedef NS_ENUM(NSUInteger, HLRequestGroupMode) {
FILE: HLNetworking/Source/Generator/Result/HLURLResult.h
type HLURLResultStatusSuccess (line 10) | typedef NS_ENUM(NSUInteger, HLURLResultStatus) {
FILE: HLNetworking/Source/Logger/HLDebugMessage.h
type NSString (line 13) | typedef NSString *HLDebugKey;
FILE: HLNetworking/Source/Logger/HLNetworkLoggerConfig.h
type HLNetworkLoggerTypeJSON (line 21) | typedef NS_ENUM(NSUInteger, HLNetworkLoggerType) {
Condensed preview — 78 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (368K chars).
[
{
"path": ".gitignore",
"chars": 151,
"preview": "HLNetworking.xcodeproj/xcuserdata/\nHLNetworking.xcworkspace/\nPods/\n*.swp\nPodfile.lock\n.DS_Store\nHLNetworking.xcodeproj/p"
},
{
"path": "HLNetworking/AppDelegate.h",
"chars": 285,
"preview": "//\n// AppDelegate.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/22.\n// Copyright © 2016年 wangshiyu13. All"
},
{
"path": "HLNetworking/AppDelegate.m",
"chars": 2047,
"preview": "//\n// AppDelegate.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/22.\n// Copyright © 2016年 wangshiyu13. All"
},
{
"path": "HLNetworking/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1077,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"size\" : \"29x29\",\n \"scale\" : \"2x\"\n },\n {\n \"idiom\""
},
{
"path": "HLNetworking/Base.lproj/LaunchScreen.storyboard",
"chars": 1740,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "HLNetworking/Base.lproj/Main.storyboard",
"chars": 1689,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "HLNetworking/HLAPICenter+home.h",
"chars": 229,
"preview": "//\n// HLAPICenter+home.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshiyu13."
},
{
"path": "HLNetworking/HLAPICenter+home.m",
"chars": 407,
"preview": "//\n// HLAPICenter+home.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshiyu13."
},
{
"path": "HLNetworking/Info.plist",
"chars": 1788,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "HLNetworking/Source/Center/HLAPICenter.h",
"chars": 369,
"preview": "//\n// HLAPICenter.h\n// HLNetworking+Lovek12\n//\n// Created by wangshiyu13 on 2016/12/9.\n// Copyright © 2016年 mykj\u0001. A"
},
{
"path": "HLNetworking/Source/Center/HLAPICenter.m",
"chars": 937,
"preview": "//\n// HLAPICenter.m\n// HLNetworking+Lovek12\n//\n// Created by wangshiyu13 on 2016/12/9.\n// Copyright © 2016年 mykj\u0001. A"
},
{
"path": "HLNetworking/Source/Center/HLAPIMacro.h",
"chars": 999,
"preview": "//\n// HLAPIMacro.h\n// HLNetworking+Lovek12\n//\n// Created by wangshiyu13 on 2016/12/10.\n// Copyright © 2016年 mykj\u0001. A"
},
{
"path": "HLNetworking/Source/Center/HLBaseObjReformer.h",
"chars": 276,
"preview": "//\n// HLBaseObjReformer.h\n// HLNetworking+Lovek12\n//\n// Created by wangshiyu13 on 2016/12/9.\n// Copyright © 2016年 my"
},
{
"path": "HLNetworking/Source/Center/HLBaseObjReformer.m",
"chars": 615,
"preview": "//\n// HLBaseObjReformer.m\n// HLNetworking+Lovek12\n//\n// Created by wangshiyu13 on 2016/12/9.\n// Copyright © 2016年 my"
},
{
"path": "HLNetworking/Source/Config/HLFormDataConfig.h",
"chars": 3217,
"preview": "//\n// HLFormDataConfig.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/23.\n// Copyright © 2016年 wangshiyu13"
},
{
"path": "HLNetworking/Source/Config/HLFormDataConfig.m",
"chars": 3215,
"preview": "//\n// HLFormDataConfig.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/23.\n// Copyright © 2016年 wangshiyu13"
},
{
"path": "HLNetworking/Source/Config/HLNetworkConfig.h",
"chars": 1140,
"preview": "//\n// HLNetworkConfig.h\n// HLPPShop\n//\n// Created by wangshiyu13 on 2016/9/19.\n// Copyright © 2016年 wangshiyu13\u0001. Al"
},
{
"path": "HLNetworking/Source/Config/HLNetworkConfig.m",
"chars": 1489,
"preview": "//\n// HLNetworkConfig.m\n// HLPPShop\n//\n// Created by wangshiyu13 on 2016/9/19.\n// Copyright © 2016年 wangshiyu13\u0001. Al"
},
{
"path": "HLNetworking/Source/Config/HLNetworkConst.h",
"chars": 2003,
"preview": "//\n// HLNetworkConst.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/22.\n// Copyright © 2017年 wangshiyu13. "
},
{
"path": "HLNetworking/Source/Config/HLNetworkMacro.h",
"chars": 32772,
"preview": "//\n// HLNetworkMacro.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 24/11/2016.\n// Copyright © 2016 wangshiyu13. "
},
{
"path": "HLNetworking/Source/Config/HLNetworkPolicyConfig.h",
"chars": 832,
"preview": "//\n// HLNetworkPolicyConfig.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshi"
},
{
"path": "HLNetworking/Source/Config/HLNetworkPolicyConfig.m",
"chars": 909,
"preview": "//\n// HLNetworkPolicyConfig.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshi"
},
{
"path": "HLNetworking/Source/Config/HLNetworkRequestConfig.h",
"chars": 1606,
"preview": "//\n// HLNetworkRequestConfig.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangsh"
},
{
"path": "HLNetworking/Source/Config/HLNetworkRequestConfig.m",
"chars": 1693,
"preview": "//\n// HLNetworkRequestConfig.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangsh"
},
{
"path": "HLNetworking/Source/Config/HLNetworkTipsConfig.h",
"chars": 1046,
"preview": "//\n// HLNetworkTipsConfig.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshiyu"
},
{
"path": "HLNetworking/Source/Config/HLNetworkTipsConfig.m",
"chars": 1370,
"preview": "//\n// HLNetworkTipsConfig.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshiyu"
},
{
"path": "HLNetworking/Source/Config/HLSecurityPolicyConfig.h",
"chars": 1028,
"preview": "//\n// HLSecurityPolicyConfig.h\n// HLPPShop\n//\n// Created by wangshiyu13 on 2016/9/19.\n// Copyright © 2016年 wangshiyu"
},
{
"path": "HLNetworking/Source/Config/HLSecurityPolicyConfig.m",
"chars": 2804,
"preview": "//\n// HLSecurityPolicyConfig.m\n// HLPPShop\n//\n// Created by wangshiyu13 on 2016/9/19.\n// Copyright © 2016年 wangshiyu"
},
{
"path": "HLNetworking/Source/Engine/HLNetworkEngine.h",
"chars": 1181,
"preview": "//\n// HLNetworkEngine.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/22.\n// Copyright © 2017年 wangshiyu13."
},
{
"path": "HLNetworking/Source/Engine/HLNetworkEngine.m",
"chars": 26821,
"preview": "//\n// HLNetworkEngine.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/22.\n// Copyright © 2017年 wangshiyu13."
},
{
"path": "HLNetworking/Source/Generator/Request/API/HLAPIRequest.h",
"chars": 3806,
"preview": "//\n// HLAPIRequest.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. Al"
},
{
"path": "HLNetworking/Source/Generator/Request/API/HLAPIRequest.m",
"chars": 10646,
"preview": "//\n// HLAPIRequest.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. Al"
},
{
"path": "HLNetworking/Source/Generator/Request/API/HLAPIRequest_InternalParams.h",
"chars": 1023,
"preview": "//\n// HLAPIRequest_InternalParams.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 "
},
{
"path": "HLNetworking/Source/Generator/Request/Base/HLURLRequest.h",
"chars": 2743,
"preview": "//\n// HLURLRequest.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. Al"
},
{
"path": "HLNetworking/Source/Generator/Request/Base/HLURLRequest.m",
"chars": 7168,
"preview": "//\n// HLURLRequest.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. Al"
},
{
"path": "HLNetworking/Source/Generator/Request/Base/HLURLRequest_InternalParams.h",
"chars": 1058,
"preview": "//\n// HLURLRequest_InternalParams.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 "
},
{
"path": "HLNetworking/Source/Generator/Request/Group/HLRequestGroup.h",
"chars": 1650,
"preview": "//\n// HLRequestGroup.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. "
},
{
"path": "HLNetworking/Source/Generator/Request/Group/HLRequestGroup.m",
"chars": 3067,
"preview": "//\n// HLRequestGroup.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. "
},
{
"path": "HLNetworking/Source/Generator/Request/Task/HLTaskRequest.h",
"chars": 1939,
"preview": "//\n// HLTaskRequest.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. A"
},
{
"path": "HLNetworking/Source/Generator/Request/Task/HLTaskRequest.m",
"chars": 5349,
"preview": "//\n// HLTaskRequest.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13. A"
},
{
"path": "HLNetworking/Source/Generator/Request/Task/HLTaskRequest_InternalParams.h",
"chars": 381,
"preview": "//\n// HLTaskRequest_InternalParams.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年"
},
{
"path": "HLNetworking/Source/Generator/Response/HLURLResponse.h",
"chars": 623,
"preview": "//\n// HLURLResponse.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshiyu13. Al"
},
{
"path": "HLNetworking/Source/Generator/Response/HLURLResponse.m",
"chars": 1617,
"preview": "//\n// HLURLResponse.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshiyu13. Al"
},
{
"path": "HLNetworking/Source/Generator/Result/HLURLResult.h",
"chars": 754,
"preview": "//\n// HLURLResult.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshiyu13. All "
},
{
"path": "HLNetworking/Source/Generator/Result/HLURLResult.m",
"chars": 2446,
"preview": "//\n// HLURLResult.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshiyu13. All "
},
{
"path": "HLNetworking/Source/HLNetworking.h",
"chars": 535,
"preview": "//\n// HLNetworking.h\n// HLPPShop\n//\n// Created by wangshiyu13 on 2016/9/19.\n// Copyright © 2016年 wangshiyu13\u0001. All r"
},
{
"path": "HLNetworking/Source/Logger/HLDebugMessage.h",
"chars": 873,
"preview": "//\n// HLDebugMessage.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshiyu13. A"
},
{
"path": "HLNetworking/Source/Logger/HLDebugMessage.m",
"chars": 3539,
"preview": "//\n// HLDebugMessage.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/2.\n// Copyright © 2017年 wangshiyu13. A"
},
{
"path": "HLNetworking/Source/Logger/HLNetworkLogger.h",
"chars": 1324,
"preview": "//\n// HLNetworkLogger.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshiyu13. "
},
{
"path": "HLNetworking/Source/Logger/HLNetworkLogger.m",
"chars": 5796,
"preview": "//\n// HLNetworkLogger.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshiyu13. "
},
{
"path": "HLNetworking/Source/Logger/HLNetworkLoggerConfig.h",
"chars": 1340,
"preview": "//\n// HLNetworkLoggerConfig.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshi"
},
{
"path": "HLNetworking/Source/Logger/HLNetworkLoggerConfig.m",
"chars": 1806,
"preview": "//\n// HLNetworkLoggerConfig.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/4.\n// Copyright © 2017年 wangshi"
},
{
"path": "HLNetworking/Source/Logger/NSNull+ToDictionary.h",
"chars": 255,
"preview": "//\n// NSNull+ToDictionary.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiy"
},
{
"path": "HLNetworking/Source/Logger/NSNull+ToDictionary.m",
"chars": 295,
"preview": "//\n// NSNull+ToDictionary.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiy"
},
{
"path": "HLNetworking/Source/Logger/UIDevice+deviceInfo.h",
"chars": 350,
"preview": "//\n// UIDevice+deviceInfo.h\n// HLNetworking\n//\n// Created by Georg Kitz on 20.08.11.\n// Copyright 2011 Aurora Apps. "
},
{
"path": "HLNetworking/Source/Logger/UIDevice+deviceInfo.m",
"chars": 9103,
"preview": "//\n// UIDevice+deviceInfo.m\n// HLNetworking\n//\n// Created by Georg Kitz on 20.08.11.\n// Copyright 2011 Aurora Apps. "
},
{
"path": "HLNetworking/Source/Logger/iPhoneTypeDefine.plist",
"chars": 3386,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "HLNetworking/Source/Manager/HLNetworkManager.h",
"chars": 3884,
"preview": "//\n// HLNetworkManager.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13"
},
{
"path": "HLNetworking/Source/Manager/HLNetworkManager.m",
"chars": 17740,
"preview": "//\n// HLNetworkManager.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/1/23.\n// Copyright © 2017年 wangshiyu13"
},
{
"path": "HLNetworking/ViewController.h",
"chars": 223,
"preview": "//\n// ViewController.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/22.\n// Copyright © 2016年 wangshiyu13. "
},
{
"path": "HLNetworking/ViewController.m",
"chars": 9333,
"preview": "//\n// ViewController.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/22.\n// Copyright © 2016年 wangshiyu13. "
},
{
"path": "HLNetworking/main.m",
"chars": 342,
"preview": "//\n// main.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2016/9/22.\n// Copyright © 2016年 wangshiyu13. All rights"
},
{
"path": "HLNetworking.podspec",
"chars": 1226,
"preview": "Pod::Spec.new do |spec|\n spec.name = 'HLNetworking'\n spec.version = '2.0.2'\n spec.license "
},
{
"path": "HLNetworking.xcodeproj/project.pbxproj",
"chars": 45545,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "HLNetworking.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 157,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:HLNetworking.xc"
},
{
"path": "HLNetworking.xcodeproj/xcshareddata/xcschemes/HLNetworking.xcscheme",
"chars": 4176,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0810\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "HLNetworkingTests/HLAPIRequestTest.m",
"chars": 11854,
"preview": "//\n// HLAPIRequestTest.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/2/9.\n// Copyright © 2017年 wangshiyu13."
},
{
"path": "HLNetworkingTests/HLManagerTests.m",
"chars": 2893,
"preview": "//\n// HLManagerTests.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/2/9.\n// Copyright © 2017年 wangshiyu13. A"
},
{
"path": "HLNetworkingTests/HLRequestGroupTests.m",
"chars": 14119,
"preview": "//\n// HLRequestGroupTests.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/2/9.\n// Copyright © 2017年 wangshiyu"
},
{
"path": "HLNetworkingTests/HLTaskRequestTest.m",
"chars": 2061,
"preview": "//\n// HLTaskRequestTest.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/2/9.\n// Copyright © 2017年 wangshiyu13"
},
{
"path": "HLNetworkingTests/HLTestCase.h",
"chars": 464,
"preview": "//\n// HLTestCase.h\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/2/9.\n// Copyright © 2017年 wangshiyu13. All r"
},
{
"path": "HLNetworkingTests/HLTestCase.m",
"chars": 2411,
"preview": "//\n// HLTestCase.m\n// HLNetworking\n//\n// Created by wangshiyu13 on 2017/2/9.\n// Copyright © 2017年 wangshiyu13. All r"
},
{
"path": "HLNetworkingTests/Info.plist",
"chars": 680,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "LICENSE",
"chars": 1508,
"preview": "Copyright (c) 2012-2017, HLNetworking (https://github.com/QianKun-HanLin)\nAll rights reserved.\n\nRedistribution and use i"
},
{
"path": "Podfile",
"chars": 155,
"preview": "source 'git@github.com:CocoaPods/Specs.git'\nplatform :ios, '8.0'\n\ntarget 'HLNetworking' do\n\tpod 'AFNetworking', '~> 3.1."
},
{
"path": "README.md",
"chars": 17390,
"preview": "
About this extraction
This page contains the full source code of the QianKun-HanLin/HLNetworking GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 78 files (317.4 KB), approximately 95.3k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.