我对iOS开发相对较新,但我正在开发应用程序以更好地了解开发。我正在使用Web服务,并希望检查用户输入的凭据。为此,我使用他们的凭据进行简单的获取请求,然后检查200的http状态。以下是我的代码:
-(BOOL)checkCredentials:(NSString *)username withPassword:(NSString *)password{
NSString *requestString = @"SOME URL";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSData *userPasswordData = [[NSString stringWithFormat:@"%@:%@", username, password] dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:@"Basic %@", base64EncodedCredential];
NSURLSessionConfiguration *sessionConfig=[NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders=@{@"Authorization":authString};
self.session=[NSURLSession sessionWithConfiguration:sessionConfig];
__block BOOL success = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error){
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
success = YES;
}
}
NSMutableDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@", jsonObject);
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
[dataTask resume];
return success;
}
我打算使用信号量等待块完成,这样我就可以检查状态码然后返回。但首先看起来我的代码只是悬而未决,我认为因为我没有发布,但ARC不允许这样做。我不确定为什么要挂。有没有更好的方法来等待块完成(没有信号量)所以我可以返回我的凭据是否有效?
还有更好的方法来传递用户名和密码,以免某人欺骗用户名和密码吗?
非常感谢任何帮助。
答案 0 :(得分:4)
想想简单!
制作自己的completionHandler
,以便您不再处理return
,来电者将负责结果验证。
您需要记住的一件事是,如果您想要修改与UI(用户界面)相关的任何内容,您需要将完成块调度到主队列,否则您将遇到意外行为,请参阅更多细节here。
将您的return
类型更改为void
并添加completion block
:
-(void)checkCredentials:(NSString *)username withPassword:(NSString *)password completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))myCompletion
{
NSString *requestString = @"http://google.com";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// Here you return exactly what the NSURLSessionDataTask downloaded
// and pass it to the caller as an another completion block
myCompletion(data, response, error);
}];
[dataTask resume];
}
来电者的代码,我认为self
是来电者:
[self checkCredentials:@"" withPassword:@"" completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error){
// Result verification's here
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
NSLog(@"SUCESS");
}
}
}];
答案 1 :(得分:3)
您的代码停止等待信号量,[dataTask resume]
永远不会被执行。
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); <=== waits here
[dataTask resume]; <=== never reached
我建议不要在这里使用信号量。而是在你的街区工作。
至于用户名/密码。如果您担心欺骗,那么HTTP上的SSL层就是答案。
答案 2 :(得分:2)
这是一个非常危险的模式,因为此调用将在网络请求完成之前阻塞。如果这是在主线程上,你的应用程序将停止响应,看门狗可能会杀了你。
除了该警告之外,该块未完成的原因是因为网络任务从未启动过。在调用resume
之前,您会在信号量上陷阱,因此您的任务永远不会运行。我也会亲自使用dispatch_group
来做等待。
为了使它更好,你需要异步重写它。基本上你的应用程序继续运行,可能会禁用输入,直到调用完成,然后运行一个块重新启用它们,或显示错误:
// Assume your login button and whatever are exposed as properties here
self.loginButton.enabled = NO;
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(!error){
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
success = YES;
}
}
NSMutableDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@", jsonObject);
// Need to be back on the main queue, the call is complete
self.loginButton.enabled = YES;
}];
[dataTask resume];
或者,只是为了保持它的方式,但解决眼前的问题,重新命令陷阱,以便在任务恢复后发生:
[dataTask resume];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); // might want to time out here instead of waiting forever
return success;