[英]NSURLConnection - Grabbing response data when using another class as a delegate, and when there is an authentication challenge
I am using my internal api to retrieve data from my server. 我正在使用内部api从服务器检索数据。 I am using Basic Authentication to achieve this.
我正在使用基本身份验证来实现此目的。 Because of the nature of APIs i am not implementing any session or anything else on my server code, so i am sending username and passwords with all of my requests.
由于API的性质,我没有在服务器代码上实现任何会话或其他任何操作,因此我在发送所有请求时都发送用户名和密码。
Because of this, i don't want to implement NSURLConnection delegates for every viewcontroller i am using. 因此,我不想为我使用的每个ViewController实现NSURLConnection委托。 So that, I created a helper class, which extends NSObject, and I set it as a NSURLConnectionDelegate.
这样,我创建了一个扩展NSObject的帮助程序类,并将其设置为NSURLConnectionDelegate。
@interface HandlerClass : NSObject <NSURLConnectionDelegate>
I implemented every method i need, and i am calling it like: 我实现了我需要的每种方法,并且我这样称呼它:
NSURL *URL = [NSURL URLWithString:@"https://url/ifuser/"];
NSLog(@"Connection ");
NSURLRequest *request = [NSURLRequest requestWithURL:URL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30.0];
NSHTTPURLResponse *response;
HandlerClass *cc = [[HandlerClass alloc] init];
cc.username = self.username.text;
cc.password = self.password.text;
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:cc];
But whatever i try, i cannot reach data response data from that delegate. 但是无论我如何尝试,我都无法从该委托那里获得数据响应数据。
I literally tried to read every piece of writing in internet, both including stackoverflow and other sites. 我从字面上试图阅读互联网上的所有作品,包括stackoverflow和其他站点。 Every solution of this requires no authentication.
每种解决方案都不需要身份验证。
But i only need the solution with authentication. 但是我只需要带有身份验证的解决方案。
Thanks. 谢谢。
~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~
EDIT: I know i did several redundant errors. 编辑:我知道我做了几个冗余错误。 But i could be able to figure out what did wrong.
但是我可以找出哪里做错了。 I just needed to use NSRunLoop to achieve my goal.
我只需要使用NSRunLoop即可实现我的目标。 Thanks all.
谢谢大家
This is what I did. 这就是我所做的。 I referred the article: Basic Authentication with a NSURLRequest in Cocoa Touch , where it uses synchronous request.
我提到了这篇文章: Cocoa Touch中使用NSURLRequest进行基本身份验证 ,其中使用了同步请求。 Here asynchronous is used for request.
这里异步用于请求。
The ConnectionHandler.h ConnectionHandler.h
#import <Foundation/Foundation.h>
@interface ConnectionHandler : NSObject<NSURLConnectionDataDelegate>
@property(nonatomic, retain) NSString *username;
@property(nonatomic, retain) NSString *password;
- (void)start;
@end
In the ConnectionHandler.m 在ConnectionHandler.m中
#import "ConnectionHandler.h"
#import "Base64.h"
@interface ConnectionHandler()
{
NSMutableData *receivedData;
NSURLConnection *connection;
}
@end
@implementation ConnectionHandler
- (id)init
{
self = [super init];
if (self) {
receivedData = [[NSMutableData alloc] init];
}
return self;
}
- (void)start
{
NSURL *url = [NSURL URLWithString:@"http://192.168.1.103/~will/"];
NSError *myError = nil;
// create a plaintext string in the format username:password
NSMutableString *loginString = (NSMutableString*)[@"" stringByAppendingFormat:@"%@:%@", self.username, self.password];
// employ the Base64 encoding above to encode the authentication tokens
NSString *encodedLoginData = [Base64 encode:[loginString dataUsingEncoding:NSUTF8StringEncoding]];
// create the contents of the header
NSString *authHeader = [@"Basic " stringByAppendingFormat:@"%@", encodedLoginData];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url
cachePolicy: NSURLRequestReloadIgnoringCacheData
timeoutInterval: 3];
// add the header to the request. Here's the $$$!!!
[request addValue:authHeader forHTTPHeaderField:@"Authorization"];
// perform the reqeust
NSURLResponse *response;
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
//a simple request may receive several response, when a new response receive, the previous received should be reset.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
//a connection may receive data several time, append the received data to existing data
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
connection = nil;
receivedData = nil;
NSLog(@"Connection failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"succeeded %d byte received",[receivedData length]);
receivedData = nil;
connection = nil;
}
@end
The Base64.m Base64.m
#import "Base64.h"
static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@implementation Base64
+(NSString *)encode:(NSData *)plainText {
int encodedLength = (4 * (([plainText length] / 3) + (1 - (3 - ([plainText length] % 3)) / 3))) + 1;
unsigned char *outputBuffer = malloc(encodedLength);
unsigned char *inputBuffer = (unsigned char *)[plainText bytes];
NSInteger i;
NSInteger j = 0;
int remain;
for(i = 0; i < [plainText length]; i += 3) {
remain = [plainText length] - i;
outputBuffer[j++] = alphabet[(inputBuffer[i] & 0xFC) >> 2];
outputBuffer[j++] = alphabet[((inputBuffer[i] & 0x03) << 4) |
((remain > 1) ? ((inputBuffer[i + 1] & 0xF0) >> 4): 0)];
if(remain > 1)
outputBuffer[j++] = alphabet[((inputBuffer[i + 1] & 0x0F) << 2)
| ((remain > 2) ? ((inputBuffer[i + 2] & 0xC0) >> 6) : 0)];
else
outputBuffer[j++] = '=';
if(remain > 2)
outputBuffer[j++] = alphabet[inputBuffer[i + 2] & 0x3F];
else
outputBuffer[j++] = '=';
}
outputBuffer[j] = 0;
NSString *result = [NSString stringWithCString:outputBuffer length:strlen(outputBuffer)];
free(outputBuffer);
return result;
}
@end
In the view controller 在视图控制器中
- (void)viewDidLoad
{
[super viewDidLoad];
ConnectionHandler *connectionHandler = [[ConnectionHandler alloc] init];
connectionHandler.username = @"username";
connectionHandler.password = @"password";
[connectionHandler start];
}
I went through a similar requirement, please have a look at the solution posted to this Question 我遇到了类似的要求,请查看发布到此问题的解决方案
The solution uses completion blocks, and it worked well to retrieve information from delegate methods implemented in another (Handler)class. 该解决方案使用完成块,并且可以很好地从另一个(Handler)类中实现的委托方法中检索信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.