NSRecursiveLock递归锁的使用html
NSRecursiveLock实际上定义的是一个递归锁,这个锁能够被同一线程屡次请求,而不会引发死锁。这主要是用在循环或递归操做中。咱们先来看一个示例:node
|
NSLock *lock = [[NSLock alloc] init];程序员
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{web
static void (^RecursiveMethod)(int);编程
RecursiveMethod = ^(int value) {json
[lock lock];安全 if (value > 0) {服务器
NSLog(@"value = %d", value);网络 sleep(2);数据结构 RecursiveMethod(value - 1); } [lock unlock]; };
RecursiveMethod(5); }); |
这段代码是一个典型的死锁状况。在咱们的线程中,RecursiveMethod是递归调用的。因此每次进入这个block时,都会去加一次锁,而从第二次开始,因为锁已经被使用了且没有解锁,因此它须要等待锁被解除,这样就致使了死锁,线程被阻塞住了。调试器中会输出以下信息:
|
value = 5 *** -[NSLock lock]: deadlock ( '(null)') *** Break on _NSLockError() to debug. |
在这种状况下,咱们就可使用NSRecursiveLock。它能够容许同一线程屡次加锁,而不会形成死锁。递归锁会跟踪它被lock的次数。每次成功的lock都必须平衡调用unlock操做。只有全部达到这种平衡,锁最后才能被释放,以供其它线程使用。
因此,对上面的代码进行一下改造,
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init]; |
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];
|
Lock的使用:
@property (readwrite, nonatomic, strong) NSRecursiveLock *lock;
self.lock = [[NSRecursiveLock alloc] init];
self.lock.name = kAFNetworkingLockName;
[self.lock lock];
if (!responseData){
_responseData = nil;
} else {
_responseData = [NSData dataWithBytes:responseData.bytes length:responseData.length];
}
[self.lock unlock];
有关IO的东西,要lock
[self performSelector:@selector(method)]的使用http://blog.sina.com.cn/s/blog_9075354e0102v0u7.html
[self method] 与 [self performSelector:@selector(method)]之间的区别(原)
今天更新项目遇到一个问题致使主线程阻塞,导致陷入死循环,解决方案:改[self invoked]为 [self performSelector: withObject:afterDelay:];故简述一下两者的区别:
performSelector
1.能够避免编译警告
2.performSelector的其余变体功能,能够用来延时调用和跨线程调用。
注意:
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
在主线程上执行指定的方法,使用默认的模式(NSDefaultRunLoopMode)。
默认的模式指:主线程中的方法进行排队,是一个循环队列,而且循环执行。
参数:
aSelector:要在主线程执行的方法,该方法不能有返回值,而且只能有一个参数。
arg:要传递的参数,若是无参数,就设为nil
wait:要执行的aSelector方法,是否立刻执行。
若是设置为YES:等待当前线程执行完之后,主线程才会执行aSelector方法;
设置为NO:不等待当前线程执行完,就在主线程上执行aSelector方法。
若是,当前线程就是主线程,那么aSelector方法会立刻执行。
该方法用途:由于iPhone编程,对UI的修改,只能在主线程上执行。能够用该方法来完成UI的修改。
接着讲performSelector
http://ronglei0324.blog.163.com/blog/static/67633223201371233549313/
对performSelector:系列方法进行了一个用法的简单分析1.- (id)performSelector:(SEL)aSelector;- (id)performSelector:(SEL)aSelectorwithObject:(id)object;- (id)performSelector:(SEL)aSelectorwithObject:(id)object1 withObject:(id)object2;这三个方法,均为同步执行,与线程无关,主主线程和子一程中都可调用成功。等同于直接调用该方法。在须要动态的去调用方法的时候去使用。
例如:[selfperformSelector:@selector(test2)];与[self test2];执行效果上彻底相同。
2.-(void)performSelector:(SEL)aSelector withObject:(id)anArgumentafterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;-(void)performSelector:(SEL)aSelector withObject:(id)anArgumentafterDelay:(NSTimeInterval)delay;这两个方法为异步执行,即便delay传参为0,仍为异步执行。只能在主线程中执行,在子线程中不会调到aSelector方法。可用于当点击UI中一个按钮会触发一个消耗系统性能的事件,在事件执行期间按钮会一直处于高亮状态,此时能够调用该方法去异步的处理该事件,就能避免上面的问题。在方法未到执行时间以前,取消方法为:
+(void)cancelPreviousPerformRequestsWithTarget:(id)aTargetselector:(SEL)aSelector object:(id)anArgument;+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;
注意:调用该方法以前或在该方法所在的viewController生命周期结束的时候去调用取消函数,以确保不会引发内存泄露。
3.-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)argwaitUntilDone:(BOOL)wait modes:(NSArray *)array;- (void)performSelectorOnMainThread:(SEL)aSelectorwithObject:(id)arg waitUntilDone:(BOOL)wait;这两个方法,在主线程和子线程中都可执行,均会调用主线程的aSelector方法
若是设置wait为YES:等待当前线程执行完之后,主线程才会执行aSelector方法;
设置为NO:不等待当前线程执行完,就在主线程上执行aSelector方法。
若是,当前线程就是主线程,那么aSelector方法会立刻执行。
注意:apple不容许程序员在主线程之外的线程中对ui进行操做,此时咱们必须调用performSelectorOnMainThread函数在主线程中完成UI的更新
4.-(void)performSelector:(SEL)aSelector onThread:(NSThread *)thrwithObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;-(void)performSelector:(SEL)aSelector onThread:(NSThread *)thrwithObject:(id)arg waitUntilDone:(BOOL)wait;调用指定线程中的某个方法。分析效果同3。
5.-(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg起子线程在后台运行?????????????本身也有一些疑问。
观察AFURLConnectionOperation中的一个方法的例子:
- (void)pause {
if ([self isPaused] || [self isFinished] || [self isCancelled]) {
return;
}
[self.lock lock];
if ([self isExecuting]) {
[self performSelector:@selector(operationDidPause)onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
dispatch_async(dispatch_get_main_queue(), ^{
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
});
}
self.state = AFOperationPausedState;
[self.lock unlock];
}
+ (NSThread *)networkRequestThread {
static NSThread*_networkRequestThread = nil;
static dispatch_once_toncePredicate;
dispatch_once(&oncePredicate,^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
});
return_networkRequestThread;
}
apple不容许程序员在主线程之外的线程中对ui进行操做,此时咱们必须调用performSelectorOnMainThread或别的函数在主线程中完成UI的更新和kvo的消息tooltian
2. 状态机
继承 NSOperation 有个很麻烦的东西要处理,就是改变状态时须要发 KVO 通知,不然这个类加入 NSOperationQueue 不可用了。 NSOperationQueue 是用 KVO 方式侦听 NSOperation 状态的改变,以判断这个任务当前是否已完成,完成的任务须要在队列中除去并释放。
AFURLConnectionOperation 对此作了个状态机,统一搞定状态切换以及发 KVO 通知的问题,内部要改变状态时,就只须要相似 self.state =AFOperationReadyState 的调用而不须要作其余了,状态改变的 KVO 通知在 setState 里发出。
总的来讲状态管理相关代码就三部分,一是限制一个状态能够切换到其余哪些状态,避免状态切换混乱,二是状态 Enum值 与NSOperation 四个状态方法的对应,三是在 setState 时统一发 KVO 通知。详见代码注释。
相关代码:AFKeyPathFromOperationState,AFStateTransitionIsValid, -setState:, -isPaused:, -isReady:, -isExecuting:,-isFinished:.
例子:
a.[self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
子线程调用异步接口,子线程须要有 Runloop 去接收异步回调事件,这里也能够每一个请求都新建一条带有 Runloop 的线程去侦听回调,但这一点好处都没有,既然是异步回调,除了处理回调内容,其余时间线程都是空闲可利用的,全部请求共用一个响应的线程就够了。
AFNetworking 用的就是第三种方式,建立了一条常驻线程专门处理全部请求的回调事件,这个模型跟 nodejs 有点相似。网络请求回调处理完,组装好数据后再给上层调用者回调,这时候回调是抛回主线程的,由于主线程是最安全的,使用者可能会在回调中更新UI,在子线程更新UI会致使各类问题,通常使用者也能够不须要关心线程问题。
b. - (void)cancelConnection{
NSDictionary *userInfo= nil;
if ([self.request URL]) {
userInfo =[NSDictionary dictionaryWithObject:[self.request URL] forKey:NSURLErrorFailingURLErrorKey];
}
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:userInfo];
if (![self isFinished]) {
if (self.connection) {
[self.connection cancel];
[self performSelector:@selector(connection:didFailWithError:)withObject:self.connection withObject:error];
} else {
// Accomodate race condition where `self.connection` hasnot yet been set before cancellation
self.error = error;
[self finish];
}
}
}
c. - (void)finish {
[self.lock lock];
self.state = AFOperationFinishedState;
[self.lock unlock];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidFinishNotification object:self];
});
}
3. NSURLConnectionDelegate
处理 NSURLConnection Delegate 的内容很少,代码也是按请求回调的顺序排列下去,十分易读,主要流程就是接收到响应的时候打开 outputStream,接着有数据过来就往 outputStream 写,在上传/接收数据过程当中会回调上层传进来的相应的callback,在请求完成回调到connectionDidFinishLoading 时,关闭 outputStream,用 outputStream 组装 responseData 做为接收到的数据,把 NSOperation 状态设为 finished,表示任务完成,NSOperation 会自动调用 completeBlock,再回调到上层。
4.setCompleteBlock
NSOperation 在 iOS4.0 之后提供了个接口 setCompletionBlock,能够传入一个 block 做为任务执行完成时(state状态机变为finished时)的回调,AFNetworking直接用了这个接口,并经过重写加了几个功能:
A.消除循环引用
在 NSOperation 的实现里,completionBlock 是 NSOperation 对象的一个成员,NSOperation 对象持有着 completionBlock,若传进来的 block 用到了 NSOperation 对象,或者 block 用到的对象持有了这个 NSOperation 对象,就会形成循环引用。这里执行完 block 后调用 [strongSelfsetCompletionBlock:nil] 把 completionBlock 设成 nil,手动释放 self(NSOperation对象) 持有的 completionBlock 对象,打破循环引用。
能够理解成对外保证传进来的block必定会被释放,解决外部使用使很容易出现的因对象关系复杂致使循环引用的问题,让使用者不知道循环引用这个概念都能正确使用。
- (void)setCompletionBlock:(void (^)(void))block {
[self.lock lock];
if (!block) {
[super setCompletionBlock:nil];
} else {
__weak __typeof(self)weakSelf = self;
[super setCompletionBlock:^ {
__strong __typeof(weakSelf)strongSelf= weakSelf;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
dispatch_group_t group =strongSelf.completionGroup ?: url_request_operation_completion_group();
dispatch_queue_t queue =strongSelf.completionQueue ?: dispatch_get_main_queue();
#pragma clang diagnostic pop
dispatch_group_async(group, queue, ^{
block();
});
dispatch_group_notify(group, url_request_operation_completion_queue(), ^{
[strongSelf setCompletionBlock:nil];
});
}];
}
[self.lock unlock];
}
2.AFHTTPRequestOperation
AFHTTPRequestOperation 继承了 AFURLConnectionOperation,把它放一块儿说是由于它没作多少事情,主要多了responseSerializer,暂停下载断点续传,以及提供接口请求成功失败的回调接口 -setCompletionBlockWithSuccess:failure:。
AFHTTPRequestOperation 继承自 AFURLConnectionOperation,使用HTTP以及HTTPS协议来处理网络请求。它封装成了一个能够使人接受的代码形式。固然AFHTTPRequestOperationManager 目前是最好的用来处理网络请求的方式,但AFHTTPRequestOperation 也有它本身的用武之地。
NSURL *URL = [NSURL URLWithString:@"http://example.com/resources/123.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer =[AFJSONResponseSerializer serializer];
[opsetCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
[[NSOperationQueuemainQueue] addOperation:op];
Batchof Operations( 许多操做一块儿进行 )
NSMutableArray *mutableOperations = [NSMutableArray array];
for (NSURL *fileURL in filesToUpload) {
NSURLRequest *request = [[AFHTTPRequestSerializer serializer]multipartFormRequestWithMethod:@"POST"URLString:@"http://example.com/upload"parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:fileURLname:@"images[]" error:nil];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[mutableOperationsaddObject:operation];
}
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[...]progressBlock:^(NSUInteger numberOfFinishedOperations, NSUIntegertotalNumberOfOperations) {
NSLog(@"%lu of %lu complete", numberOfFinishedOperations, totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
NSLog(@"All operations in batch complete");
}];
[[NSOperationQueue mainQueue]addOperations:operations waitUntilFinished:NO];
3.AFURLRequestSerialization
AFURLRequestSerialization用于帮助构建NSURLRequest,主要作了两个事情:
1.构建普通请求:格式化请求参数,生成HTTP Header。
2.构建multipart请求。
分别看看它在这两点具体作了什么,怎么作的。
1.构建普通请求
A.格式化请求参数
通常咱们请求都会按key=value的方式带上各类参数,GET方法参数直接加在URL上,POST方法放在body上,NSURLRequest没有封装好这个参数的解析,只能咱们本身拼好字符串。AFNetworking提供了接口,让参数能够是NSDictionary, NSArray,NSSet这些类型,再由内部解析成字符串后赋给NSURLRequest。
第一部分是用户传进来的数据,支持包含NSArray,NSDictionary,NSSet这三种数据结构。
第二部分是转换成AFNetworking内本身的数据结构,每个key-value对都用一个对象AFQueryStringPair表示,做用是最后能够根据不一样的字符串编码生成各自的key=value字符串。主要函数是AFQueryStringPairsFromKeyAndValue,详见源码注释。
第三部分是最后生成NSURLRequest可用的字符串数据,而且对参数进行url编码,在AFQueryStringFromParametersWithEncoding这个函数里。
最后在把数据赋给NSURLRequest时根据不一样的HTTP方法分别处理,对于GET/HEAD/DELETE方法,把参数加到URL后面,对于其余如POST/PUT方法,把数据加到body上,并设好HTTP头,告诉服务端字符串的编码。
static NSString *AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncodingstringEncoding) {
NSMutableArray*mutablePairs = [NSMutableArray array];
for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
[mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]];
}
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;
// Sort dictionary keys to ensure consistent ordering inquery string, which is important when deserializing potentially ambiguoussequences, such as an array of dictionaries
for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor ]]) {
id nestedValue =[dictionary objectForKey: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 {
[mutableQueryStringComponentsaddObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
}
returnmutableQueryStringComponents;
}
B.HTTP Header
AFNetworking帮你组装好了一些HTTP请求头,包括语言Accept-Language,根据 [NSLocalepreferredLanguages] 方法读取本地语言,高速服务端本身能接受的语言。还有构建 User-Agent,以及提供Basic Auth 认证接口,帮你把用户名密码作 base64 编码后放入 HTTP 请求头。详见源码注释。
C.其余格式化方式
HTTP请求参数不必定是要key=value形式,能够是任何形式的数据,能够是json格式,苹果的plist格式,二进制protobuf格式等,AFNetworking提供了方法能够很容易扩展支持这些格式,默认就实现了json和plist格式。详见源码的类AFJSONRequestSerializer和AFPropertyListRequestSerializer。
2.构建multipart请求
构建Multipart请求是占篇幅很大的一个功能,AFURLRequestSeria
Multipart是HTTP协议为web表单新增的上传文件的协议,协议文档是rfc1867,它基于HTTP的POST方法,数据一样是放在body上,跟普通POST方法的区别是数据不是key=value形式,key=value形式难以表示文件实体,为此Multipart协议添加了分隔符,有本身的格式结构,大体以下:lization里2/3的代码都是在作这个事。
—AaB03x
content-disposition: form-data;name=“name"
bang
--AaB03x
content-disposition: form-data;name="pic"; filename=“content.txt"
Content-Type: text/plain
... contents of bang.txt ...
--AaB03x--
以上表示数据name=bang以及一个文件,content.txt是文件名,… contents of bang.txt …是文件实体内容。分隔符—AaB03x是能够自定义的,写在HTTP头部里:
Content-type: multipart/form-data,boundary=AaB03x
每个部分都有本身的头部,代表这部分的数据类型以及其余一些参数,例如文件名,普通字段的key。最后一个分隔符会多加两横,表示数据已经结束:—AaB03x—。
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
[mutableHeaderssetValue:[NSString stringWithFormat:@"form-data; name=\"%@\";filename=\"%@\"", name, fileName]forKey:@"Content-Disposition"];
[mutableHeaderssetValue:mimeType forKey:@"Content-Type"];
AFHTTPBodyPart *bodyPart= [[AFHTTPBodyPart alloc] init];
bodyPart.stringEncoding = self.stringEncoding;
bodyPart.headers =mutableHeaders;
bodyPart.boundary = self.boundary;
bodyPart.body = fileURL;
bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue];
[self.bodyStream appendHTTPBodyPart:bodyPart];
B.实现
接下来讲说怎样构造Multipart里的数据,最简单的方式就是直接拼数据,要发送一个文件,就直接把文件全部内容读取出来,再按上述协议加上头部和分隔符,拼接好数据后扔给NSURLRequest的body就能够发送了,很简单。
构建本身的数据结构,只保存要上传的文件地址,边上传边拼数据,上传是分片的,拼数据也是分片的,拼到文件实体部分时直接从原来的文件分片读取。这方法没上述两种的问题,只是实现起来也没上述两种简单,AFNetworking就是实现这第三种方法,并且还更进一步,除了文件,还能够添加多个其余不一样类型的数据,包括NSData,和InputStream。
AFNetworking 里 multipart 请求的使用方式是这样:
▪ AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
▪ NSDictionary *parameters = @{@"foo": @"bar"};
▪ NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
▪ [manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id formData) {
▪ [formData appendPartWithFileURL:filePath name:@"image" error:nil];
▪ } success:^(AFHTTPRequestOperation *operation, id responseObject) {
▪ NSLog(@"Success: %@", responseObject);
▪ } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
▪ NSLog(@"Error: %@", error);
}];
[self.bodyStream appendHTTPBodyPart:bodyPart];
具体用处:
NSData *postData =[[post description] dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
NSString *soapAction = [NSString stringWithFormat:@"%@%@",OPERATOR_NAME_SPACE_URL , action];
NSURL *url=[[NSURL alloc]initWithString:OPERATOR_WSDL_URL];
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]init];
[request setTimeoutInterval: 30];
[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[request setURL: url] ;
[request setHTTPMethod:@"POST"];
[request setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setValue:soapAction forHTTPHeaderField:@"SOAPAction"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
4. AFSecurityPolicy
AFSecurityPolicy用于验证HTTPS请求的证书
NSURLConnection已经封装了https链接的创建、数据的加密解密功能,咱们直接使用NSURLConnection是能够访问 https网站的,但NSURLConnection并无验证证书是否合法,没法避免中间人攻击。要作到真正安全通信,须要咱们手动去验证服务端返回的 证书,AFSecurityPolicy封装了证书验证的过程,让用户能够轻易使用,除了去系统信任CA机构列表验证,还支持SSL Pinning方式的验证。使用方法:
//把服务端证书(须要转换成cer格式)放到APP项目资源里,AFSecurityPolicy会自动寻找根目录下全部cer文件
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
securityPolicy.allowInvalidCertificates = YES;
[AFHTTPRequestOperationManager manager].securityPolicy = securityPolicy;
[manager GET:@"https://example.com/" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
Allowing Invalid SSL Certificates( 容许不合法的SSL证书 )
AFHTTPRequestOperationManager *manager =[AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates= YES; // not recommended for production
5. AFURLSessionManager(开头有代码例子)
AFURLSessionManager 建立了一个管理一个NSURLSession的对象,基于一个指定的 NSURLSessionConfiguration 对象,它与如下的这些协议融合在一块儿( <NSURLSessionTaskDelegate> , <NSURLSessionDataDelegate> , <NSURLSessionDownloadDelegate> , <NSURLSessionDelegate> )。
Creating a Download Task( 建立一个下载任务 )
Creating an Upload Task for a Multi-PartRequest, with Progress( 建立一个复杂的请求,并附带进度 )
6. AFHTTPRequestOperationManager
将通用的与服务器应用交互的操做封装了起来,包括了请求的建立,回复的序列化,网络指示器的监测,安全性,固然还有请求操做的管理。
GET Request( GET请求 )
POST URL-Form-EncodedRequest( 附带表单编码的POST请求 )
POST Multi-Part Request( 复杂的POST请求 )