diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug.xcodeproj/project.pbxproj b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug.xcodeproj/project.pbxproj index 1990e3f5..b8ffc74a 100644 --- a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug.xcodeproj/project.pbxproj +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -14,6 +14,8 @@ 14A334922568D62500772436 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 14A334912568D62500772436 /* Assets.xcassets */; }; 14A334952568D62500772436 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14A334932568D62500772436 /* LaunchScreen.storyboard */; }; 14A334982568D62500772436 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14A334972568D62500772436 /* main.m */; }; + 14ED0256256A480700D370FD /* SQQueryStringPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ED0255256A480700D370FD /* SQQueryStringPair.m */; }; + 14ED0267256A4AD700D370FD /* SQURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ED0266256A4AD700D370FD /* SQURLRequestSerialization.m */; }; 1E4C433D320B90193A1EE719 /* Pods_AFNetworking_Debug.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E27C56A0FCB7F71F556F4D1 /* Pods_AFNetworking_Debug.framework */; }; /* End PBXBuildFile section */ @@ -31,6 +33,10 @@ 14A334942568D62500772436 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 14A334962568D62500772436 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 14A334972568D62500772436 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 14ED0254256A480700D370FD /* SQQueryStringPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQQueryStringPair.h; sourceTree = ""; }; + 14ED0255256A480700D370FD /* SQQueryStringPair.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SQQueryStringPair.m; sourceTree = ""; }; + 14ED0265256A4AD700D370FD /* SQURLRequestSerialization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQURLRequestSerialization.h; sourceTree = ""; }; + 14ED0266256A4AD700D370FD /* SQURLRequestSerialization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SQURLRequestSerialization.m; sourceTree = ""; }; 3E27C56A0FCB7F71F556F4D1 /* Pods_AFNetworking_Debug.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AFNetworking_Debug.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 67E409C126A533A0A2F1DA57 /* Pods-AFNetworking-Debug.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking-Debug.debug.xcconfig"; path = "Target Support Files/Pods-AFNetworking-Debug/Pods-AFNetworking-Debug.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -74,6 +80,10 @@ 14A334892568D62400772436 /* SceneDelegate.m */, 14A3348B2568D62400772436 /* ViewController.h */, 14A3348C2568D62400772436 /* ViewController.m */, + 14ED0254256A480700D370FD /* SQQueryStringPair.h */, + 14ED0255256A480700D370FD /* SQQueryStringPair.m */, + 14ED0265256A4AD700D370FD /* SQURLRequestSerialization.h */, + 14ED0266256A4AD700D370FD /* SQURLRequestSerialization.m */, 14A3348E2568D62400772436 /* Main.storyboard */, 14A334912568D62500772436 /* Assets.xcassets */, 14A334932568D62500772436 /* LaunchScreen.storyboard */, @@ -97,7 +107,6 @@ 67E409C126A533A0A2F1DA57 /* Pods-AFNetworking-Debug.debug.xcconfig */, 002F3802D60E85956ACBBB58 /* Pods-AFNetworking-Debug.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -216,8 +225,10 @@ files = ( 14A3348D2568D62400772436 /* ViewController.m in Sources */, 14A334872568D62400772436 /* AppDelegate.m in Sources */, + 14ED0267256A4AD700D370FD /* SQURLRequestSerialization.m in Sources */, 14A334982568D62500772436 /* main.m in Sources */, 14A3348A2568D62400772436 /* SceneDelegate.m in Sources */, + 14ED0256256A480700D370FD /* SQQueryStringPair.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQQueryStringPair.h b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQQueryStringPair.h new file mode 100644 index 00000000..31a9fdf5 --- /dev/null +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQQueryStringPair.h @@ -0,0 +1,19 @@ +// +// SQQueryStringPair.h +// AFNetworking-Debug +// +// Created by 朱双泉 on 2020/11/22. +// + +#import + +@interface SQQueryStringPair : NSObject + +@property (readwrite, nonatomic, strong) id field; +@property (readwrite, nonatomic, strong) id value; + +- (instancetype)initWithField:(id)field value:(id)value; + +- (NSString *)URLEncodedStringValue; + +@end diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQQueryStringPair.m b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQQueryStringPair.m new file mode 100644 index 00000000..670dc9d7 --- /dev/null +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQQueryStringPair.m @@ -0,0 +1,59 @@ +// +// SQQueryStringPair.m +// AFNetworking-Debug +// +// Created by 朱双泉 on 2020/11/22. +// + +#import "SQQueryStringPair.h" + +@implementation SQQueryStringPair + +NSString * SQPercentEscapedStringFromString(NSString *string) { +// return string; + static NSString * const kSQCharactersGeneralDelimitersToEncode = @":#[]@"; + static NSString * const kSQCharactersSubDelimitersToEncode = @"!$&'()*+,;="; + NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + [allowedCharacterSet removeCharactersInString:[kSQCharactersGeneralDelimitersToEncode stringByAppendingString:kSQCharactersSubDelimitersToEncode]]; + NSString *encoded = [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + + static NSUInteger const batchSize = 50; + NSUInteger index = 0; + NSMutableString *escaped = @"".mutableCopy; + while (index < string.length) { + NSUInteger length = MIN(string.length - index, batchSize); + NSRange range = NSMakeRange(index, length); + range = [string rangeOfComposedCharacterSequencesForRange:range]; + NSString *substring = [string substringWithRange:range]; + NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + [escaped appendString:encoded]; + index += range.length; + } + return encoded; +} + +- (instancetype)initWithField:(id)field value:(id)value { + self = [super init]; + if (!self) { + return nil; + } + + self.field = field; + self.value = value; + + return self; +} + +- (NSString *)URLEncodedStringValue { + if (!self.value || [self.value isEqual:[NSNull null]]) { + return SQPercentEscapedStringFromString([self.field description]); + } else { + return [NSString stringWithFormat:@"%@=%@", SQPercentEscapedStringFromString([self.field description]), SQPercentEscapedStringFromString([self.value description])]; + } +} + +- (NSString *)description { + return [self URLEncodedStringValue]; +} + +@end diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQURLRequestSerialization.h b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQURLRequestSerialization.h new file mode 100644 index 00000000..d506be4c --- /dev/null +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQURLRequestSerialization.h @@ -0,0 +1,18 @@ +// +// SQURLRequestSerialization.h +// AFNetworking-Debug +// +// Created by 朱双泉 on 2020/11/22. +// + +#import + +@interface SQURLRequestSerialization : NSObject + +NSString * SQQueryStringFromParameters(NSDictionary *parameters); + +NSArray * SQQueryStringPairFromDictionary(NSDictionary *dictionary); + +NSArray * SQQueryStringPairsFromKeyAndValue(NSString *key, id value); + +@end diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQURLRequestSerialization.m b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQURLRequestSerialization.m new file mode 100644 index 00000000..81b76470 --- /dev/null +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/SQURLRequestSerialization.m @@ -0,0 +1,52 @@ +// +// SQURLRequestSerialization.m +// AFNetworking-Debug +// +// Created by 朱双泉 on 2020/11/22. +// + +#import "SQURLRequestSerialization.h" +#import "SQQueryStringPair.h" + +@implementation SQURLRequestSerialization + +NSString * SQQueryStringFromParameters(NSDictionary *parameters) { + NSMutableArray *mutablePairs = [NSMutableArray array]; + for (SQQueryStringPair *pair in SQQueryStringPairFromDictionary(parameters)) { + [mutablePairs addObject:[pair URLEncodedStringValue]]; + } + return [mutablePairs componentsJoinedByString:@"&"]; +} + +NSArray * SQQueryStringPairFromDictionary(NSDictionary *dictionary) { + return SQQueryStringPairsFromKeyAndValue(nil, dictionary); +} + +NSArray * SQQueryStringPairsFromKeyAndValue(NSString *key, id value) { + NSMutableArray *mutableQueryStringComponents = [NSMutableArray array]; + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)]; + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = value; + for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { + id nestedValue = dictionary[nestedKey]; + if (nestedValue) { + [mutableQueryStringComponents addObjectsFromArray:SQQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]; + } + } + } else if ([value isKindOfClass:[NSArray class]]) { + NSArray *array = value; + for (id nestedValue in array) { + [mutableQueryStringComponents addObjectsFromArray:SQQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)]; + } + } else if ([value isKindOfClass:[NSSet class]]) { + NSSet *set = value; + for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { + [mutableQueryStringComponents addObjectsFromArray:SQQueryStringPairsFromKeyAndValue(key, obj)]; + } + } else { + [mutableQueryStringComponents addObject:[[SQQueryStringPair alloc] initWithField:key value:value]]; + } + return mutableQueryStringComponents; +} + +@end diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/ViewController.m b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/ViewController.m index e82457ce..0586dc35 100644 --- a/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/ViewController.m +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1-Debug/AFNetworking-Debug/ViewController.m @@ -7,6 +7,8 @@ #import "ViewController.h" #import +#import "SQQueryStringPair.h" +#import "SQURLRequestSerialization.h" @interface ViewController () @property (nonatomic, weak) IBOutlet UIProgressView *progressView; @@ -173,6 +175,55 @@ - (void)debug_AFNURLRequestSerialSerialization { NSLog(@"QueryString: %@", AFQueryStringFromParameters(@{@"a": @1, @"b": @2, @"c": @3})); // QueryString: a=1&b=2&c=3 + + NSLog(@"AFURLRequestSerializationErrorDomain: %@", AFURLRequestSerializationErrorDomain); + // AFURLRequestSerializationErrorDomain: com.alamofire.error.serialization.request + NSLog(@"AFNetworkingOperationFailingURLRequestErrorKey: %@", AFNetworkingOperationFailingURLRequestErrorKey); + // AFNetworkingOperationFailingURLRequestErrorKey: com.alamofire.serialization.request.error.response + NSLog(@"kAFUploadStream3GSuggestedPacketSize: %lu", kAFUploadStream3GSuggestedPacketSize); + // kAFUploadStream3GSuggestedPacketSize: 16384 + NSLog(@"kAFUploadStream3GSuggestedDelay: %f", kAFUploadStream3GSuggestedDelay); + // kAFUploadStream3GSuggestedDelay: 0.200000 + + SQQueryStringPair *pair = [[SQQueryStringPair alloc] initWithField:@"a" value:@1]; + NSLog(@"%@", [pair URLEncodedStringValue]); + // a=1 + + SQQueryStringPair *pair2 = [[SQQueryStringPair alloc] initWithField:@"b" value:nil]; + NSLog(@"%@", [pair2 URLEncodedStringValue]); + // b + + NSLog(@"%@", SQQueryStringPairsFromKeyAndValue(@"a", @1)); + /** + ( + "a=1" + ) + */ + + NSLog(@"%@", SQQueryStringPairsFromKeyAndValue(@"a", @{@"b": @{@"c": @3}, @"d": @""})); + /** + ( + "a[b][c]=3", + "a[d]=" + ) + */ + NSLog(@"%@", SQQueryStringPairsFromKeyAndValue(@"a", @[@"b", @{@"c": @3}, @"d"])); + /** + ( + "a[]=b", + "a[][c]=3", + "a[]=d" + ) + */ + NSLog(@"%@", SQQueryStringPairFromDictionary(@{@"a": @{@"b": @{@"c": @3}, @"d": @""}})); + /** + ( + "a[b][c]=3", + "a[d]=" + ) + */ + NSLog(@"%@", SQQueryStringFromParameters(@{@"a": @{@"b": @{@"c": @3}, @"d": @""}})); + // a[b][c]=3&a[d]= } @end diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.h b/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.h index 57c6e4db..57d80ed1 100644 --- a/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.h +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.h @@ -427,49 +427,49 @@ forHTTPHeaderField:(NSString *)field; #pragma mark - ///---------------- -/// @name Constants +/// @name 常数 ///---------------- /** - ## Error Domains + ##错误域 - The following error domain is predefined. + 以下错误域是预定义的。 - - `NSString * const AFURLRequestSerializationErrorDomain` + -`NSString * const AFURLRequestSerializationErrorDomain` - ### Constants + ###常数 - `AFURLRequestSerializationErrorDomain` - AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. + AFURLRequestSerializationErrorDomain AFURLRequestSerializer错误。 + AFURLRequestSerializationErrorDomain的错误代码对应于NSURLErrorDomain的代码。 */ FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain; /** - ## User info dictionary keys + ##用户信息字典键 - These keys may exist in the user info dictionary, in addition to those defined for NSError. + 除了为NSError定义的密钥外,这些密钥还可以存在于用户信息字典中。 - - `NSString * const AFNetworkingOperationFailingURLRequestErrorKey` + -`NSString * const AFNetworkingOperationFailingURLRequestErrorKey` - ### Constants + ###常数 - `AFNetworkingOperationFailingURLRequestErrorKey` - The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`. + AFNetworkingOperationFailingURLRequestErrorKey + 相应的值为“ NSURLRequest”,其中包含与错误相关联的操作请求。 该密钥仅存在于“ AFURLRequestSerializationErrorDomain”中。 */ FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey; /** - ## Throttling Bandwidth for HTTP Request Input Streams + ## HTTP请求输入流的限制带宽 - @see -throttleBandwidthWithPacketSize:delay: + @see -throttleBandwidthWithPacketSize:delay: - ### Constants + ###常数 - `kAFUploadStream3GSuggestedPacketSize` - Maximum packet size, in number of bytes. Equal to 16kb. + kAFUploadStream3GSuggestedPacketSize + 最大数据包大小,以字节数为单位。 等于16kb。 - `kAFUploadStream3GSuggestedDelay` - Duration of delay each time a packet is read. Equal to 0.2 seconds. + kAFUploadStream3GSuggestedDelay + 每次读取数据包的延迟时间。 等于0.2秒。 */ FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize; FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay; diff --git a/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.m b/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.m index f60b6f9d..86167e29 100644 --- a/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.m +++ b/SQDebug/AFNetworking/AFNetworking-4.0.1/AFNetworking/AFURLRequestSerialization.m @@ -33,19 +33,17 @@ typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, id parameters, NSError *__autoreleasing *error); /** - Returns a percent-escaped string following RFC 3986 for a query string key or value. - RFC 3986 states that the following characters are "reserved" characters. - - General Delimiters: ":", "#", "[", "]", "@", "?", "/" - - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" - - In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow - query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" - should be percent-escaped in the query string. - - parameter string: The string to be percent-escaped. - - returns: The percent-escaped string. + 返回遵循RFC 3986的查询字符串键或值的百分比转义字符串。 + RFC 3986声明以下字符为“保留”字符。 + -通用分隔符:“:”,“#”,“ [”,“]”,“ @”,“?”,“ /” + -子定界符:“!”,“ $”,“&”,“'”,“(”,“)”,“ *”,“ +”,“,”,“,”,“ =” + + 在RFC 3986-3.4节中,它指出“?” 和“ /”字符不应转义以允许查询字符串包含URL。 因此,所有“保留”字符(“?”除外) 和“ /”应该在查询字符串中转义。 + -参数字符串:要百分号转义的字符串。 + -返回:转义百分比的字符串。 */ NSString * AFPercentEscapedStringFromString(NSString *string) { - static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4 + static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // 不包括 ”?” 或“ /”(由于RFC 3986-第3.4节) static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; @@ -63,7 +61,7 @@ NSUInteger length = MIN(string.length - index, batchSize); NSRange range = NSMakeRange(index, length); - // To avoid breaking up character sequences such as 👴🏻👮🏽 + //为了避免破坏诸如👴🏻👮🏽之类的字符序列 range = [string rangeOfComposedCharacterSequencesForRange:range]; NSString *substring = [string substringWithRange:range]; @@ -136,7 +134,7 @@ - (NSString *)URLEncodedStringValue { if ([value isKindOfClass:[NSDictionary class]]) { NSDictionary *dictionary = value; - // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries + // 对字典键进行排序以确保查询字符串中的顺序一致,这在反序列化可能含糊的序列(例如字典数组)时很重要 for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { id nestedValue = dictionary[nestedKey]; if (nestedValue) { diff --git a/SQDebug/AFNetworking/README.md b/SQDebug/AFNetworking/README.md index 45d86cf0..d7cf81e0 100644 --- a/SQDebug/AFNetworking/README.md +++ b/SQDebug/AFNetworking/README.md @@ -1,11 +1,13 @@ ## AFNetworking -[Github 官方文档](https://github.com/AFNetworking/AFNetworking) -[AFNetworking 4.0.1 源码下载](https://github.com/AFNetworking/AFNetworking/archive/4.0.1.zip) - >AFNetworking是一个适用于iOS,macOS,watchOS和tvOS的令人愉悦的网络库。它建立在Foundation URL loading System的基础上,扩展了Cocoa中内置的强大的高级网络抽象。它具有模块化的体系结构,以及精心设计的,功能丰富的API,使用起来很愉快。 -### AFNetworking Debug +- [Github 官方文档](https://github.com/AFNetworking/AFNetworking) +- [AFNetworking 4.0.1 源码下载](https://github.com/AFNetworking/AFNetworking/archive/4.0.1.zip) +- [关注我 获取中文版源码](https://github.com/coderZsq/coderZsq.project.ios/tree/master/SQDebug) + + +## 0x00 准备工作 ```shell $ pod init @@ -49,6 +51,8 @@ info.plist root \\中添加ATS $ npm i koa koa-router koa-send koa-multer ``` +## 0x01 搭建服务器体验AFNetworking + ```js const Router = require('koa-router'); const send = require('koa-send'); @@ -337,6 +341,8 @@ Reachability: Reachable via WiFi Reachability: Not Reachable ``` +## 0x02 导览AFNetworing知识架构 + ```shell $ cd AFNetworking-4.0.1 $ tree @@ -403,7 +409,10 @@ $ tree └── AFURLResponseSerialization.m ``` -AFNetworking.h +```objc +#import <"AFNetworking.h"> +``` + ```objc #import #import @@ -470,6 +479,8 @@ Contains: Mac OS X和iPhone的TARGET_条件的自动配置 #import "AFHTTPSessionManager.h" ``` +## 0x03 AFNetworking请求序列化.h文件详解 + ```objc #import "AFURLRequestSerialization.h" ``` @@ -658,10 +669,6 @@ typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { @end ``` -```objc -@interface AFHTTPRequestSerializer : NSObject -``` - ```objc /** AFHTTPRequestSerializer符合AFURLRequestSerialization和AFURLResponseSerialization协议,提供查询字符串/ URL格式编码的参数序列化和默认请求标头的具体基础实现,以及响应状态代码和内容类型验证。 @@ -900,6 +907,305 @@ AFPropertyListRequestSerializer是AFHTTPRequestSerializer的子类,它使用NS @end ``` +```objc +///---------------- +/// @name 常数 +///---------------- + +/** + ##错误域 + + 以下错误域是预定义的。 + + -`NSString * const AFURLRequestSerializationErrorDomain` + + ###常数 + + AFURLRequestSerializationErrorDomain AFURLRequestSerializer错误。 + AFURLRequestSerializationErrorDomain的错误代码对应于NSURLErrorDomain的代码。 + */ +FOUNDATION_EXPORT NSString * const AFURLRequestSerializationErrorDomain; + +/** + ##用户信息字典键 + + 除了为NSError定义的密钥外,这些密钥还可以存在于用户信息字典中。 + + -`NSString * const AFNetworkingOperationFailingURLRequestErrorKey` + + ###常数 + + AFNetworkingOperationFailingURLRequestErrorKey + 相应的值为“ NSURLRequest”,其中包含与错误相关联的操作请求。 该密钥仅存在于“ AFURLRequestSerializationErrorDomain”中。 + */ +FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLRequestErrorKey; + +/** + ## HTTP请求输入流的限制带宽 + + @see -throttleBandwidthWithPacketSize:delay: + + ###常数 + + kAFUploadStream3GSuggestedPacketSize + 最大数据包大小,以字节数为单位。 等于16kb。 + + kAFUploadStream3GSuggestedDelay + 每次读取数据包的延迟时间。 等于0.2秒。 + */ +FOUNDATION_EXPORT NSUInteger const kAFUploadStream3GSuggestedPacketSize; +FOUNDATION_EXPORT NSTimeInterval const kAFUploadStream3GSuggestedDelay; +``` + +```objc +NSLog(@"AFURLRequestSerializationErrorDomain: %@", AFURLRequestSerializationErrorDomain); +``` + +``` +AFURLRequestSerializationErrorDomain: com.alamofire.error.serialization.request +``` + +```objc +NSLog(@"AFNetworkingOperationFailingURLRequestErrorKey: %@", AFNetworkingOperationFailingURLRequestErrorKey); +``` + +``` +AFNetworkingOperationFailingURLRequestErrorKey: com.alamofire.serialization.request.error.response +``` + +```objc +NSLog(@"kAFUploadStream3GSuggestedPacketSize: %lu", kAFUploadStream3GSuggestedPacketSize); +``` + +``` +kAFUploadStream3GSuggestedPacketSize: 16384 +``` + +```objc +NSLog(@"kAFUploadStream3GSuggestedDelay: %f", kAFUploadStream3GSuggestedDelay); +``` + +``` +kAFUploadStream3GSuggestedDelay: 0.200000 +``` + +## 0x04 AFNetworking请求序列化.m详解 + +```objc +NSString * const AFURLRequestSerializationErrorDomain = @"com.alamofire.error.serialization.request"; +NSString * const AFNetworkingOperationFailingURLRequestErrorKey = @"com.alamofire.serialization.request.error.response"; +``` + +```objc +/** + AFURLRequestSerialization.m line: 191 + */ +typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, id parameters, NSError *__autoreleasing *error); +``` + +```objc +/** + 返回遵循RFC 3986的查询字符串键或值的百分比转义字符串。 + RFC 3986声明以下字符为“保留”字符。 + -通用分隔符:“:”,“#”,“ [”,“]”,“ @”,“?”,“ /” + -子定界符:“!”,“ $”,“&”,“'”,“(”,“)”,“ *”,“ +”,“,”,“,”,“ =” + + 在RFC 3986-3.4节中,它指出“?” 和“ /”字符不应转义以允许查询字符串包含URL。 因此,所有“保留”字符(“?”除外) 和“ /”应该在查询字符串中转义。 + -参数字符串:要百分号转义的字符串。 + -返回:转义百分比的字符串。 + */ +NSString * AFPercentEscapedStringFromString(NSString *string) { + static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // 不包括 ”?” 或“ /”(由于RFC 3986-第3.4节) + static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; + + NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; + [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; + + // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028 + // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + + static NSUInteger const batchSize = 50; + + NSUInteger index = 0; + NSMutableString *escaped = @"".mutableCopy; + + while (index < string.length) { + NSUInteger length = MIN(string.length - index, batchSize); + NSRange range = NSMakeRange(index, length); + + //为了避免破坏诸如👴🏻👮🏽之类的字符序列 + range = [string rangeOfComposedCharacterSequencesForRange:range]; + + NSString *substring = [string substringWithRange:range]; + NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; + [escaped appendString:encoded]; + + index += range.length; + } + + return escaped; +} +``` + +```objc +@interface AFQueryStringPair : NSObject +@property (readwrite, nonatomic, strong) id field; +@property (readwrite, nonatomic, strong) id value; + +- (instancetype)initWithField:(id)field value:(id)value; + +- (NSString *)URLEncodedStringValue; +@end + +@implementation AFQueryStringPair + +- (instancetype)initWithField:(id)field value:(id)value { + self = [super init]; + if (!self) { + return nil; + } + + self.field = field; + self.value = value; + + return self; +} + +- (NSString *)URLEncodedStringValue { + if (!self.value || [self.value isEqual:[NSNull null]]) { + return AFPercentEscapedStringFromString([self.field description]); + } else { + return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedStringFromString([self.field description]), AFPercentEscapedStringFromString([self.value description])]; + } +} + +@end +``` + +```objc +SQQueryStringPair *pair = [[SQQueryStringPair alloc] initWithField:@"a" value:@1]; +``` + +```objc +NSLog(@"%@", [pair URLEncodedStringValue]); +``` + +``` +a=1 +``` + +```objc +SQQueryStringPair *pair2 = [[SQQueryStringPair alloc] initWithField:@"b" value:nil]; +``` + +```objc +NSLog(@"%@", [pair2 URLEncodedStringValue]); +``` + +``` +b +``` + +```objc +FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary); +FOUNDATION_EXPORT NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value); + +NSString * AFQueryStringFromParameters(NSDictionary *parameters) { + NSMutableArray *mutablePairs = [NSMutableArray array]; + for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) { + [mutablePairs addObject:[pair URLEncodedStringValue]]; + } + + return [mutablePairs componentsJoinedByString:@"&"]; +} + +NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) { + return AFQueryStringPairsFromKeyAndValue(nil, dictionary); +} + +NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) { + NSMutableArray *mutableQueryStringComponents = [NSMutableArray array]; + + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)]; + + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = value; + // 对字典键进行排序以确保查询字符串中的顺序一致,这在反序列化可能含糊的序列(例如字典数组)时很重要 + for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { + id nestedValue = dictionary[nestedKey]; + if (nestedValue) { + [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]; + } + } + } else if ([value isKindOfClass:[NSArray class]]) { + NSArray *array = value; + for (id nestedValue in array) { + [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)]; + } + } else if ([value isKindOfClass:[NSSet class]]) { + NSSet *set = value; + for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) { + [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)]; + } + } else { + [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]]; + } + + return mutableQueryStringComponents; +} +``` + +```objc +NSLog(@"%@", SQQueryStringPairsFromKeyAndValue(@"a", @1)); +``` +``` +( + "a=1" +) +``` + +```objc +NSLog(@"%@", SQQueryStringPairsFromKeyAndValue(@"a", @{@"b": @{@"c": @3}, @"d": @""})); +``` + +``` +( + "a[b][c]=3", + "a[d]=" +) +``` + +```objc +NSLog(@"%@", SQQueryStringPairsFromKeyAndValue(@"a", @[@"b", @{@"c": @3}, @"d"])); +``` + +``` +( + "a[]=b", + "a[][c]=3", + "a[]=d" +) +``` + +```objc +NSLog(@"%@", SQQueryStringPairFromDictionary(@{@"a": @{@"b": @{@"c": @3}, @"d": @""}})); +``` + +``` +( + "a[b][c]=3", + "a[d]=" +) +``` + +```objc +NSLog(@"%@", SQQueryStringFromParameters(@{@"a": @{@"b": @{@"c": @3}, @"d": @""}})); +``` + +``` +a[b][c]=3&a[d]= +``` + ```objc #import "AFURLSessionManager.h" ```