AFNetWorking(3.0)源码分析(五)——AFHTTPRequestSerializer & AFHTTPResponseSerializer

2023-05-16

在前面的几篇博客中,我们分析了AFURLSessionMangerd以及它的子类AFHTTPSessionManager。我们对AF的主要两个类,有了一个比较全面的了解。

对于AFHTTPSessionManager,当其在要发送请求时,会调用AFHTTPRequestSerializer 来组装请求。 而当请求获得了响应,需要作出解析时,又会调用对应的response serializer来解析返回的data。

对于服务器响应的解析过程,在AFHTTPSessionManager中,是通过AFHTTPResponseSerializer来实现的。

AFHTTPResponseSerializer

AFHTTPResponseSerializer 作为http response的解析类,其实是作为基类存在的,对于真正的数据解析,并没有提供有用的代码,而是要让子类实现。在AFHTTPResponseSerializer 中,仅提供了最基础的配置信息,如response接受何种语言类型,何种状态码等。以及子类的一些公共的功能函数validateResponse

@interface AFHTTPResponseSerializer : NSObject <AFURLResponseSerialization>

- (instancetype)init;

@property (nonatomic, assign) NSStringEncoding stringEncoding DEPRECATED_MSG_ATTRIBUTE("The string encoding is never used. AFHTTPResponseSerializer only validates status codes and content types but does not try to decode the received data in any way.");

/**
 Creates and returns a serializer with default configuration.
 */
+ (instancetype)serializer;

///-----------------------------------------
/// @name Configuring Response Serialization
///-----------------------------------------

@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes;


@property (nonatomic, copy, nullable) NSSet <NSString *> *acceptableContentTypes;


- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response
                    data:(nullable NSData *)data
                   error:(NSError * _Nullable __autoreleasing *)error;

@end

AFHTTPResponseSerializerstringEncoding属性的注释中可以看到,AFHTTPResponseSerializer仅是指定了http response有效的status codescontent types,并没有对response data做任何解析,因此,stringEncoding属性AFHTTPResponseSerializer中应当是从未被使用的。

The string encoding is never used. AFHTTPResponseSerializer only validates status codes and content types but does not try to decode the received data in any way.

AFHTTPResponseSerializer同时提供了一个父类方法validateResponse,用来判定当前的http response是否符合设定的status codescontent types,这个方法,在子类中是可以通用的:

- (BOOL)validateResponse:(NSHTTPURLResponse *)response
                    data:(NSData *)data
                   error:(NSError * __autoreleasing *)error
{
    BOOL responseIsValid = YES;
    NSError *validationError = nil;

    if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
        if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]] &&
            !([response MIMEType] == nil && [data length] == 0)) {

            if ([data length] > 0 && [response URL]) {
                NSMutableDictionary *mutableUserInfo = [@{
                                                          NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
                                                          NSURLErrorFailingURLErrorKey:[response URL],
                                                          AFNetworkingOperationFailingURLResponseErrorKey: response,
                                                        } mutableCopy];
                if (data) {
                    mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
                }

                validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);
            }

            responseIsValid = NO;
        }

        if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
            NSMutableDictionary *mutableUserInfo = [@{
                                               NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
                                               NSURLErrorFailingURLErrorKey:[response URL],
                                               AFNetworkingOperationFailingURLResponseErrorKey: response,
                                       } mutableCopy];

            if (data) {
                mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
            }

            validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);

            responseIsValid = NO;
        }
    }

    if (error && !responseIsValid) {
        *error = validationError;
    }

    return responseIsValid;
}

实现比较简单,我们就不再分析。

AFHTTPResponseSerializer的声明中,我们可以发现,AFHTTPResponseSerializer是遵循AFURLResponseSerialization协议的。而AFURLResponseSerialization协议的定义如下:

@protocol AFURLResponseSerialization <NSObject, NSSecureCoding, NSCopying>

/**
 The response object decoded from the data associated with a specified response.

 @param response The response to be processed.
 @param data The response data to be decoded.
 @param error The error that occurred while attempting to decode the response data.

 @return The object decoded from the specified response data.
 */
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
                           data:(nullable NSData *)data
                          error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;

@end

仅定义了一个方法,responseObjectForResponse:data:error:。这个方法是用来真正的解析request请求返回的data的。其返回值为id类型,也就是解析后的mode对象,他可以是任何类型,也就为我们解析请求的扩展,提供了可能。

对于基类AFHTTPResponseSerializer,它responseObjectForResponse:data:error:方法的实现是:

- (id)responseObjectForResponse:(NSURLResponse *)response
                           data:(NSData *)data
                          error:(NSError *__autoreleasing *)error
{
    [self validateResponse:(NSHTTPURLResponse *)response data:data error:error];

    return data;
}

可以看到,其直接将data返回,没有做任何解析。因此,需要我们继承AFHTTPResponseSerializer,并重写responseObjectForResponse:data:error:方法,才能够做到对响应的真正解析。

我们可以自定义子类,而AF也默认给我们提供了几个子类的实现:

/**
 `AFJSONResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes JSON responses.

 By default, `AFJSONResponseSerializer` accepts the following MIME types, which includes the official standard, `application/json`, as well as other commonly-used types:

 - `application/json`
 - `text/json`
 - `text/javascript`

 In RFC 7159 - Section 8.1, it states that JSON text is required to be encoded in UTF-8, UTF-16, or UTF-32, and the default encoding is UTF-8. NSJSONSerialization provides support for all the encodings listed in the specification, and recommends UTF-8 for efficiency. Using an unsupported encoding will result in serialization error. See the `NSJSONSerialization` documentation for more details.
 */
@interface AFJSONResponseSerializer : AFHTTPResponseSerializer

/**
 `AFXMLParserResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLParser` objects.

 By default, `AFXMLParserResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types:

 - `application/xml`
 - `text/xml`
 */
@interface AFXMLParserResponseSerializer : AFHTTPResponseSerializer

/**
 `AFXMLDocumentResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects.

 By default, `AFXMLDocumentResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types:

 - `application/xml`
 - `text/xml`
 */
@interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer

/**
 `AFPropertyListResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects.

 By default, `AFPropertyListResponseSerializer` accepts the following MIME types:

 - `application/x-plist`
 */
@interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer

/**
 `AFImageResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes image responses.

 By default, `AFImageResponseSerializer` accepts the following MIME types, which correspond to the image formats supported by UIImage or NSImage:

 - `image/tiff`
 - `image/jpeg`
 - `image/gif`
 - `image/png`
 - `image/ico`
 - `image/x-icon`
 - `image/bmp`
 - `image/x-bmp`
 - `image/x-xbitmap`
 - `image/x-win-bitmap`
 */
@interface AFImageResponseSerializer : AFHTTPResponseSerializer


/**
 `AFCompoundSerializer` is a subclass of `AFHTTPResponseSerializer` that delegates the response serialization to the first `AFHTTPResponseSerializer` object that returns an object for `responseObjectForResponse:data:error:`, falling back on the default behavior of `AFHTTPResponseSerializer`. This is useful for supporting multiple potential types and structures of server responses with a single serializer.
 */
@interface AFCompoundResponseSerializer : AFHTTPResponseSerializer

注意一下,最后一个AFCompoundResponseSerializer,其实是一个集合,可以为其添加好几种ResponseSerializer到它里面。这是为了防止在response type未知的情况下,用组合式ResponseSerializer来尝试是否有一种对应的解析器。

AFJSONResponseSerializer

对于response 解析器的实现,每个子类都有不同的实现。但它们的共同点是:

  1. 均继承自AFHTTPResponseSerializer
  2. 都会重写responseObjectForResponse:data:error:方法

我们可以单独拎出来AFJSONResponseSerializer,来看一下它是如何重写responseObjectForResponse:data:error:方法的:

- (id)responseObjectForResponse:(NSURLResponse *)response
                           data:(NSData *)data
                          error:(NSError *__autoreleasing *)error
{
    if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
        if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
            return nil;
        }
    }

    // Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
    // See https://github.com/rails/rails/issues/1742
    BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
    
    if (data.length == 0 || isSpace) {
        return nil;
    }
    
    NSError *serializationError = nil;
    
    id responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];

    if (!responseObject)
    {
        if (error) {
            *error = AFErrorWithUnderlyingError(serializationError, *error);
        }
        return nil;
    }
    
    if (self.removesKeysWithNullValues) {
        return AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
    }

    return responseObject;
}

其核心也就是调用了NSJSONSerialization的方法,做JSON格式的解析。

上面的代码还是比较好理解的。那么,AF又是在什么时候调用Response Serializer的解析方法

- (id)responseObjectForResponse:(NSURLResponse *)response
                           data:(NSData *)data
                          error:(NSError *__autoreleasing *)error

的呢?自然,应该是在Server返回response的时候。

让我们追根溯源,还记得在基类AFURLSessionManager中,我们曾提到过,对于每一个Session task的响应,AFURLSessionManager 都会分配一个AFURLSessionManagerTaskDelegate来处理。其中,就包含对于系统NSURLSessionTaskDelegate的处理。

对于NSURLSessionTaskDelegate


- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error

响应里面,AFURLSessionManagerTaskDelegate有这么一段:

else {
        dispatch_async(url_session_manager_processing_queue(), ^{
            NSError *serializationError = nil;
            responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
	。。。
}

在这里会看到manager调用了responseSerializer对响应作出解析。而这里的responseSerializer自然不是某个具体的类,而是符合AFURLResponseSerialization协议的一个id类型:

id <AFURLResponseSerialization> responseSerializer;

AF通过这种协议的抽象,使得我们可以在具体应用中任意替换解析对象,如,可以替换为上面提到的AFJSONResponseSerializer,因为它正符合AFURLResponseSerialization协议

AFHTTPRequestSerializer

在AF中,对于request的序列化,同样使用了抽象协议的方式:


@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>

/**
 Returns a request with the specified parameters encoded into a copy of the original request.

 @param request The original request.
 @param parameters The parameters to be encoded.
 @param error The error that occurred while attempting to encode the request parameters.

 @return A serialized request.
 */
- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(nullable id)parameters
                                        error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;

@end

在上一章中,我们分析了AFHTTPRequestSerializer的部分实现,它是怎么支持GET/PUT/HEAD/POST/DELETE等method的。

在这里,我们就不再去分析其余的实现了,而是关注一下在AFHTTPRequestSerializer中用到的一个小技巧。

在AF的AFHTTPRequestSerializer中,需要解决这么一个问题,就是,对于NSMutableURLRequest来说,除了设置URL和http body,还有许多控制属性可以让用户设置,如设置请求超时timeoutInterval,cache策略等。

对应的,在AFHTTPRequestSerializer中自然也是添加了这些对应的属性来运行用户设置NSMutableURLRequest

@interface AFHTTPRequestSerializer : NSObject <AFURLRequestSerialization>

@property (nonatomic, assign) BOOL allowsCellularAccess;

@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;

@property (nonatomic, assign) BOOL HTTPShouldHandleCookies;

@property (nonatomic, assign) BOOL HTTPShouldUsePipelining;

@property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;

@property (nonatomic, assign) NSTimeInterval timeoutInterval;

那么,当AFHTTPRequestSerializer在组装NSMutableURLRequest时,又是如何知道用户设置了这些属性,并设置这些属性到NSMutableURLRequest呢?

一般的,我们是不是想这样解决,给这每一个属性都设置一个和系统默认值相等的初始值,在组装request的时候,将这些值全部赋值给NSMutableURLRequest? 如下面这样做:

// 先初始化一些和系统默认值相等的初始值
_allowsCellularAccess = YES;
_cachePolicy = NSURLRequestUseProtocolCachePolicy;
...

// 将这些属性赋值给request;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
request.allowsCellularAccess = self.allowsCellularAccess;
request.cachePolicy = self.cachePolicy;
...

上面这种做法也没错,但是不是感觉有点挫?一大堆的属性赋值,但用户可能仅仅改变了其中一个或什么属性都没有改。

比较好的做法是,我们需要知道用户修改了那些属性,然后我们仅仅设置用户所修改的属性。AF确实也是这么做的,而且用了比较巧的方法。

首先,在AFHTTPRequestSerializer中,注册了KVO监听:


    self.mutableObservedChangedKeyPaths = [NSMutableSet set];
    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
        if ([self respondsToSelector:NSSelectorFromString(keyPath)]) { // 通过KVO的方式,检测并记录自身的属性变换
            [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext]; // AFHTTPRequestSerializerObserverContext 这到底是什么context?
        }
    }

AFHTTPRequestSerializer要监听的Key数组定义为:

static NSArray * AFHTTPRequestSerializerObservedKeyPaths() {
    static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))];
    });

    return _AFHTTPRequestSerializerObservedKeyPaths;
}

对应的,重写响应属性的Set方法,并触发KVO:

- (void)setAllowsCellularAccess:(BOOL)allowsCellularAccess {
    [self willChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
    _allowsCellularAccess = allowsCellularAccess;
    [self didChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
}

我们来看KVO的响应函数:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(__unused id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if (context == AFHTTPRequestSerializerObserverContext) {
        // 将为空的参数取出,将赋值的参数记录下来,等到生成request的时候,使用这些值
        if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
            [self.mutableObservedChangedKeyPaths removeObject:keyPath];
        } else {
            [self.mutableObservedChangedKeyPaths addObject:keyPath];
        }
    }
}

可以看到,当修改对应的属性时,KVO会通报被修改的keyPath,AF中用self.mutableObservedChangedKeyPaths这个set来记录修改的属性的名称。

当最后要配置request时,仅需要根据这个keyPath 集合,利用KVC取出对应的属性并赋值即可:

    // 3.设置mutableRequest 对应的属性值。这是通过KVO用户设置相关的属性操作
    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
        if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
            [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
        }
    }

这是AF中关于KVO和KVC的一个很好的应用场景。

总结

这就是我们分析AFHTTPRequestSerializerAFHTTPResponseSerializer的全部内容,关于这部分的代码,并不是特别复杂,只要静下心来分析其调用路径基本就能够了解。关于AF中KVC和KVO的灵活应用,也是值得我们借鉴的地方。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AFNetWorking(3.0)源码分析(五)——AFHTTPRequestSerializer & AFHTTPResponseSerializer 的相关文章

  • afnetworking 3.0 迁移:如何使用标头和 HTTP 正文进行 POST

    我正在尝试向 youtube API 发出一个包含 HTTPHeader 字段和 HTTP 正文的 POST 请求 以前在 AFNetworking 2 0 版本中 我曾经这样做过 效果很好 NSDictionary parameters
  • 我使用 AFNetWorking 时出现错误代码 -1011

    我在我们的客户公司做服务 我尝试通过 AFNetWorking 从他们的服务器获取一些信息 我们的客户鼓励使用 AFNetWorking 我使用 AFNetWorking 做了一些示例 并且成功了 但是当我使用我们的客户 URL 之一来获取
  • AFNetworking 2.0:NSLocalizedDescription=请求失败:不可接受的内容类型:text/html

    我尝试过了GET来自Apple主页的html AFHTTPRequestOperationManager manager AFHTTPRequestOperationManager manager manager GET http www
  • NSURLSession用于网络图片下载+缓存

    有许多第三方库用于加载网络图像 然后将其存储到磁盘和 或内存中 然而它是好简单使用简单的 NSURLSession API 调用来实现它 这是代码 NSURLCache myCache NSURLCache alloc initWithMe
  • 只要互联网连接可用,就将数据发送到服务器 iOS

    我正在开发一个 iOS 应用程序 我想做的是 每当用户通过设置应用程序打开 关闭互联网时 我想向设备设置一些通知 简而言之 我想在互联网连接可用时向服务器发送一些数据 存储在 NSUserDefaults 中 假设互联网连接在 2 3 天后
  • AFNetworking - 滚动 UITableView 时淡入图像上的动画

    我有一个表视图 它使用 AFNetworking 的延迟加载和占位符图像来显示图像 我正在尝试实现一种在加载时从占位符淡入图像的方法 我的代码在这里有效 但是如果在滚动表格时加载图像 一切看起来都很奇怪并且表格停止滚动 同样的情况也发生在水
  • Domain=NSURLErrorDomain Code=-1021“请求正文流已耗尽”

    我收到 NSURLErrorDomain Code 1021 请求正文流已耗尽 NSLocalizedDescription 请求正文流耗尽 NSUnderlyingError 0x2088c080 请求正文流耗尽 上传多张大尺寸图片时会出
  • NSURLSession/NSURLConnection HTTP 加载在 iOS 9 上失败

    尝试在 iOS9 上运行我现有的应用程序 但在使用时失败AFURLSessionManager block NSURLSessionDataTask task self sessionManager dataTaskWithRequest
  • AFNetworking 和 Swift

    我正在尝试使用 Swift 获取 JSON 响应 我嗅探了请求和响应 gt 一切正常 然而返回值始终是nil let httpClient AppDelegate appDelegate httpRequestOperationManage
  • AFNetworking - 如何为一个键指定多个值

    我正在尝试使用 AFHTTPClient 方法 postPath 将一个参数键的多个值传递给 HTTP 请求 但是 参数变量是 NSDictionary 因此我无法为我的键 email 设置多个值 我尝试将电子邮件值作为逗号分隔的字符串发送
  • PHAsset + AF 网络。真机上无法上传文件到服务器

    目前我正在使用以下代码将文件上传到服务器 NSURLRequest urlRequest AFHTTPRequestSerializer serializer multipartFormRequestWithMethod POST URLS
  • 即使用户强制退出 iOS Objective C 中的应用程序,如何在后台继续下载新图像?

    我想下载300张左右的许多图像 并将其显示在UI中 我有两个问题 如果应用程序位于前台 并且假设用户将其发送到后台模式 通过单击主页按钮 那么我如何确保下载继续 如果用户强制退出应用程序 双击主页按钮并从应用程序切换器中滑动应用程序 那么如
  • 如何使用 AFNetworking 2 批量请求?

    因此 我正在使用 AFNetworking 2 0 重写 iOS 7 的应用程序 但遇到了一次发送一批请求并跟踪其进度的问题 在旧的 AFNetworking 中有enqueueBatchOfHTTPRequestOperations pr
  • AFNetworking 和 jSON

    我正在跟踪来自 Web 服务 api 的 json 响应 我想从 json 中提取产品数据 我也想使用 AFNetworking 来实现这一点 products product id 1170 name zzzz sort order 0
  • AFNetworking:重试操作时访问完成处理程序

    给出一些上下文 我正在尝试为身份验证错误实现一个全局错误处理程序 使用令牌身份验证 而不是基本身份验证 它应该尝试重新身份验证 然后重复原始失败的请求 请参阅我之前的问题 AFNetworking 全局处理错误并重复请求 https sta
  • AFNetworking 返回 NSCFData; registerHTTPOperationClass 的问题[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我是 AF
  • Objective C 内存管理,包括块、ARC 和非 ARC

    我使用块已经有一段时间了 但我觉得在 ARC 和非 ARC 环境中 我都怀念一些关于内存管理的事情 我觉得更深层次的理解会让我避免很多内存泄漏 AFNetworking 是我在特定应用程序中对 Blocks 的主要使用 大多数时候 在操作的
  • AFNetworking 2.0取消特定任务

    我正在尝试 afnetworking 2 0 只是想弄清楚如何取消特定任务 旧的方法是使用类似的东西 self cancelAllHTTPOperationsWithMethod POST path user receipts 但我在 2
  • 使用 AFNetworking 发送多张图像

    我正在开发一款消息应用程序 用户还可以互相发送图片 当用户发送多张图片时 我会并行发送它们 在发送第二张图片之前 我不会等待第一张图片完成上传 搬到之前AFNetworking我成功地做到了这一点ASIFormDataRequest 事实上
  • AFNetworking + 取消所有请求

    当我想停止使用 AFNetworking 构建的同步引擎中的所有当前请求时 我确实遇到了问题 我有 5 个不同的 URL 需要查询 如果前一个查询正确执行 则每个查询都会启动 这非常有效 我想随时停止同步过程 所以我的代码是 void ca

随机推荐

  • 程序员的硬件设备

    程序员的硬件设备 程序员的工作台 很多人从网上 或者公司里 xff0c 看到程序员开发的工作台是这样的 其实这是个误区 xff0c 不同的人习惯不一样 xff0c 对于程序员来说 xff0c 一台性能好点的电脑就做够了 市场上有很多驻场外包
  • scp 本地复制文件到服务器

    1 本地复制文件到服务器 scp Users guolm Desktop ROOT war root 64 192 168 1 228 opt tomcat webapps 2 服务器到本地文件 scp root 64 192 168 1
  • Wireshark 认识捕获的分析数据包(及各个分层协议的介绍)

    综述 xff1a 认识Wireshark捕获数据包 当我们对Wireshark主窗口各部分作用了解了 xff0c 学会捕获数据了 xff0c 接下来就该去认识这些捕获的数据包了 Wireshark将从网络中捕获到的二进制数据按照不同的协议包
  • 禁用virtualbox自带的dhcp服务

    在你安装虚拟机的系统上面 xff0c 打开cmd xff1a cd D cd D softInstall VMvirtualbox6 D softInstall VMvirtualbox6 gt VBoxManage list dhcpse
  • MATLAB并行计算

    先上图 xff0c 图中求500次随机矩阵的特征值 xff0c 串行14 85s xff0c 并行3 63s 串行计算 tic S1 61 1 for i 61 1 500 S1 61 S1 43 max eig rand i end di
  • libsvm参数说明

    因为要用svm做regression xff0c 所以看了一些关于libsvm xff0c 总结以备用 libsvm在训练model的时候 xff0c 有如下参数要设置 xff0c 当然有默认的参数 xff0c 但是在具体应用方面效果会大大
  • Windows C# RabbitMQ 安装--配置--信息收发

    前言 近期要实现一个图片异步上传的需求 xff0c 需要用到RabbitMQ xff0c 辅助客户端完成对高并发请求的处理 一 安装Erlang 由于RabbitMQ服务器是用Erlang语言编写 xff0c 所以我们需要先安装Erlang
  • .MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1

    MalformedJsonException Use JsonReader setLenient true to accept malformed JSON at line 1 column 1 path 像这种低级错误 xff0c 我今天
  • 离线升级curl采坑

    先在线yum打包 1 安装repo rpm Uvh http www city fan org ftp contrib yum repo rhel6 x86 64 city fan org release 2 1 rhel6 noarch
  • uos桌面系统获取串口日志

    文章目录 一 准备工作1 问题机器2 收集日志机器 二 串口线连接三 收集日志机器上查看串口信息四 问题机器上设置gurb五 cutecom调试串口六 使用minicom工具收集串口信息 一 准备工作 1 问题机器 span class t
  • Ubuntu18.04.3安装GTX1650显卡驱动 安装CUDA 安装CUDNN

    0 前期准备 禁用BIOS的secure boot xff0c 即disable它 xff0c 如果不关闭 xff0c 使用第三方源安装显卡驱动会安装后不能使用 1 禁用nouveau 1 创建文件 xff0c 如果没有下载vim编辑器 x
  • mybatis中resultMap使用之返回分组数据

    1 resultMap 1 1 引言 resultMap是mybatis最重要的强大元素 通过描述数据的关系结构 xff0c 将结果集进行映射到java类或java bean中 xff0c 达到结果集复杂处理的目的 本文解决的主要问题的分组
  • 项目中使用JPush推送,遇到的问题

    JPush初始化错误 Android版本是4 0以上的 xff0c JPush包是1 60的 报错 xff1a 02 24 18 46 54 306 E AndroidRuntime 22522 FATAL EXCEPTION Thread
  • HIDL最全编译流程

    想了解HIDL介绍的可以参考 HIDL概述 xff0c 本篇文章主要介绍HIDL的详细编译流程及简单的客户端应用 xff08 C 43 43 跟Android客户端的应用 xff09 一 准备工作 整一套源码 xff0c Android O
  • 【mysql】如何在MySQL中导入超大的SQL文件?

    mysql 如何在MySQL中导入超大的SQL文件 xff1f 方法 1 在navicat中导入 xff08 速度慢 xff09 2 使用source命令导入 xff08 速度快 xff09 第一种很简单 xff0c 本文只介绍第二种 步骤
  • (转)imageIO异常:Unsupported Image Type, 不支持图像类型

    是不是在使用iamgeio导入图片的时候出现了这个异常呢 xff1a javax imageio IIOException Unsupported Image Type 如果你确定图片格式没有错 xff0c 那我想你可能使用过photosh
  • 遗传算法与进化算法

    引言 1858年7月1日C R 达尔文与A R 华莱士在伦敦林奈学会上宣读了进化论的论文 xff0c 至此进化理论深入人心 xff0c 为广大吃瓜群众开辟了一个思想的新的天地 而我们的机器学习大师们向来喜欢从生物学家那里找灵感 xff0c
  • Git使用手册/Git教程:git pull origin 拉取代码到本地,解决拉取代码时发生的文件冲突

    相关文章 xff1a 关于验证是否存在ssh配置以及生成SSH Key的方法可以参照文章 xff1a Git使用手册 生成SSH Key 关于SSH Key的使用和公钥在gitHub gitLab的配置等 xff0c 请参考文章 xff1a
  • 基于SSM的社区团购小程序的设计与实现

    社区团购的设计与实现 该项目含有源码 论文等资料 配套开发软件 软件安装教程 项目发布教程等 系统功能完整 xff0c 适合作为毕业设计 课程设计 数据库大作业学习使用 项目功能介绍 社区团购系统中的功能模块主要是实现管理员服务端 xff1
  • AFNetWorking(3.0)源码分析(五)——AFHTTPRequestSerializer & AFHTTPResponseSerializer

    在前面的几篇博客中 xff0c 我们分析了AFURLSessionMangerd以及它的子类AFHTTPSessionManager 我们对AF的主要两个类 xff0c 有了一个比较全面的了解 对于AFHTTPSessionManager