brief introduction
AFNet Working is an open source library for developing iOS program mainstream network requests using Objective-c.
AF Networking Organization Structure
AFNet Working is mainly divided into five parts. NSURLSession, Reachability, security, Serialization, UIKit. Among them, NSURLSession is the soul of the whole network request open source library, which provides a rich network request interface to the outside world. Including GET, POST, HEAD, PUT, DELETE, and file upload interface.
The organization structure of AFNet Working is as follows:
Source code interpretation
1.NSURLSession
NSURLSession includes AFURLSession Manager and AFHTTPSession Manager. AFHTTPSession Manager inherits AFURLSession Manager and provides an interface for network requests. The GET and POST interfaces we use most often are called at the bottom.
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress success:(void (^)(NSURLSessionDataTask *, id))success failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
The realization of the whole method is as follows:
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress success:(void (^)(NSURLSessionDataTask *, id))success failure:(void (^)(NSURLSessionDataTask *, NSError *))failure { NSError *serializationError = nil; NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; if (serializationError) { if (failure) { dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); } return nil; } __block NSURLSessionDataTask *dataTask = nil; dataTask = [self dataTaskWithRequest:request uploadProgress:uploadProgress downloadProgress:downloadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { if (failure) { failure(dataTask, error); } } else { if (success) { success(dataTask, responseObject); } } }]; return dataTask; }
Except for the interface of file upload, file upload involves data fragmentation, using a `-(NSURLSession Data Task) POST:(NSString) URLString
parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure`Interface, the full implementation of this interface is as follows:
- (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { NSError *serializationError = nil; NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; if (serializationError) { if (failure) { dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); } return nil; } __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { if (failure) { failure(task, error); } } else { if (success) { success(task, responseObject); } } }]; [task resume]; return task; }
AFURLSessionManager
AFURLSession Manager is the core of the whole network request framework.
Create url_session_manager_creation_queue, url_session_manager_processing_queue,
url_session_manager_completion_group, these three are singletons.
AFURLSession Manager manages session s in a serial queue manner. Security policies use default policies. `- (NSURLSession Data Task) dataTask WithRequest:(NSURLRequest) request
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler`In a safe way, create a dataTask,Finally, join in mutableTask Of**NSMutableDictionary**Medium.
AFURLSession Manager is the foundation of AFHTTPSession Manager. It provides download Task, upload Task, data Task and other encapsulation for AFHTTPSession Manager.
2.AFNetworkReachabilityManager
AFNetwork Reachability Manager monitors network status. The methods are as follows:
static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; if (isNetworkReachable == NO) { status = AFNetworkReachabilityStatusNotReachable; } #if TARGET_OS_IPHONE else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { status = AFNetworkReachabilityStatusReachableViaWWAN; } #endif else { status = AFNetworkReachabilityStatusReachableViaWiFi; } return status; }
According to the incoming SCNetwork Reachability Flags flag, the corresponding network status is returned.
3.AFSecurityPolicy
AF Security Policy, a security policy for network requests. This class provides three security strategies:
typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { AFSSLPinningModeNone, AFSSLPinningModePublicKey, AFSSLPinningModeCertificate, };
The default security policy is AFSSL Pinning ModeNone, and we can set the corresponding security policy as needed.
The actual setting of chestnuts in development is as follows:
- (void)setupSecurityPolicy { AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey]; [securityPolicy setAllowInvalidCertificates:YES]; [securityPolicy setValidatesDomainName:YES]; self.sessionManager.securityPolicy = securityPolicy; }
We used SSL to encrypt the transmitted data in order to achieve secure data transmission.
4.AFURLRequestSerialization
It is a serialization of requests made by clients.
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(id)parameters error:(NSError *__autoreleasing *)error { NSParameterAssert(request); NSMutableURLRequest *mutableRequest = [request mutableCopy]; [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) { if (![request valueForHTTPHeaderField:field]) { [mutableRequest setValue:value forHTTPHeaderField:field]; } }]; NSString *query = nil; if (parameters) { if (self.queryStringSerialization) { NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); if (serializationError) { if (error) { *error = serializationError; } return nil; } } else { switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: query = AFQueryStringFromParameters(parameters); break; } } } if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { if (query && query.length > 0) { mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; } } else { // #2864: an empty string is a valid x-www-form-urlencoded payload if (!query) { query = @""; } if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; } return mutableRequest; }
The request parameters are spliced, serialized, request Content-Type is set, and then the serialized parameters are set to HTTPBody.
The corresponding serialization class AFJSONRequestSerializer & AFPropertyListRequestSerializer can serialize request parameters into application/json or application/x-plist format according to Content-Type.
5.AFURLResponseSerialization
Response serialization is to parse response data into corresponding formats using a data parser. The parsers provided by AFURLResponseSerialization are:
- AFJSONResponseSerializer -> application/json/text/json/text/javascript
- AFXMLParserResponseSerializer -> application/xml/text/xml
- AFPropertyListResponseSerializer -> application/x-plist
- AFImageResponseSerializer - > Image / jpeg / image / GIF / image / png, these three are commonly used, there are several other, you can see in the source code.
- The AFCompound Response Serializer synthetic parser is a collection of the above.