您的位置:首页 > 其它

AFNetworking3同步请求另类解决方案(阻塞线程)

2016-04-08 20:46 597 查看

1.情景:

由于公司业务需求,需要在iPad端架设服务器,当用户手机扫码连接wifi时,公司后台会重定向到我iPad端的服务器,并通过Socket将必要的用户信息发给iPad端,iPad验证用户信息,然后发送xml请求给AC(我们公司用的Aruba),请求通过则再由iPad重定向给用户一个成功页面,否则失败页面。 真的是折腾了好久。废话不多说,进入正题。

2.使用AFN 3.0做同步请求的原因:

由于连接AC是一个https的请求,需要做证书验证,可能通过CA验证的证书成本高吧,并没有去搞证书,于是必须绕过证书验证。 曾经的NSURLConnection中有didReceiveChallenge几个代理方法可以实现,但是毕竟Apple现在推荐NSURLSession嘛,尝试了,也不知道什么原因,AC总是连不上。 于是去AFN里面找了一会儿,发现AFN的策略配置,给manager设置允许无效证书和不验证域名,代码如下:

//request
NSURL *URL = [NSURL URLWithString:urlString];
NSMutableURLRequest *request1 = [NSMutableURLRequest requestWithURL:URL];
[request1 setHTTPMethod:@"POST"];
[request1 setHTTPBody:postBody];
[request1 setValue:@"application/xml;charset=utf-8" forHTTPHeaderField:@"Content-Type"];

//session
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

//policy(此处为重点,绕开证书验证)
AFSecurityPolicy *policy        = [AFSecurityPolicy defaultPolicy];
policy.allowInvalidCertificates = YES;
policy.validatesDomainName      = NO;
manager.securityPolicy          = policy;


3.同步请求解决办法

由于在httpServer中需要另一个对象中的AFN的方法发送请求给AC验证授理用户,并根据AC返回的结果,作出不同的重定向页面。 如果不做任何处理,未等到AC的返回结果直接就return了,没法重定向到规定的页面。 试过信号量机制,NSCondition等等,不遂人愿。 最后想到一个究级方法,while()阻塞。

while (!condition)
{
 sleep(1);
}


这很好理解,在A对象中,某方法内,不满足某条件就继续等待,知道条件满足继续执行接下来的,这种另类的形式实现了同步的方式。但是如果实在UI线程中会卡住UI,做如下更改:

while (_statusInfo == nil) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}


给出我的代码部分:

    if ([order isEqualToString:@"wifi"]) {
[NSThread detachNewThreadSelector:@selector(queryAndAddUser) toTarget:self withObject:nil];
while (_statusInfo == nil) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; }
}
if ([_statusInfo isEqualToString:@"Ok"]) {
resp = [[HTTPRedirectResponse alloc] initWithPath:@"http://****"];
}else{
resp = [[HTTPRedirectResponse alloc] initWithPath:@"http://****"];
}
return resp;
}

#pragma mark - 查询增加用户
- (void)queryAndAddUser{
ACBridge *ac = [[ACBridge alloc] init];
[ac queryUserWithHostURL:@"192.168.89.202" Port:@"4343" ForIP:self.clientIP FromObjcet:self];
}


其中:_statusInfo是从B对象请求方法的回掉中传回来的,通过验证_statusInfo是否满足要求来决定是否阻塞当前线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息