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

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是否满足要求来决定是否阻塞当前线程。

你可能感兴趣的:(多线程)