I am trying to isolate logic responsible for authentication and retriving the TOKEN inside the function. I have the problem with returning the string with token from BLOCK of NSURLConnetcion.
It causues semantic error
: Incompatible block pointer types sending
'NSString *(^)(NSURLResponse *__strong, NSData *__strong, NSError *__strong)'
to parameter of type
'void (^)(NSURLResponse *__strong, NSData *__strong, NSError *__strong)'
I am completly newbie to Objective-C, so please be forgiving. Below is my function.
- (NSString*)getToken: (NSString *)username andPassword: (NSString *) password {
NSMutableURLRequest *request1 = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:@"http://127.0.0.1:8000/auth_ex"]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20];
__block NSString * tokens;
[request1 setHTTPMethod:@"POST"];
NSString * body1 = [NSString stringWithFormat:@"email=%@&password=%@",username,password];
[request1 setHTTPBody: [body1 dataUsingEncoding:NSUTF8StringEncoding]];
NSOperationQueue * queue1 = [[NSOperationQueue alloc]init];
[NSURLConnection
sendAsynchronousRequest:request1 queue:queue1 completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if ([data length] >0 && connectionError == nil){
NSDictionary* token = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
tokens = [token objectForKeyedSubscript:@"token"];
return tokens;
}
else{
return @"NOT AUTHORIZEd";
}
}];
}
The variable
tokens
is declared outside of the block but accessible from inside the block. Therefore theif
statement doesn't need toreturn tokens
and the else statement should just betokens = @"NOT AUTHORIZED";
Note that your block is being called from some framework code, and that code doesn't expect anything to be returned, hence the completionHandler is declared as
void
, and you aren't allowed to return values from avoid
function.I should add that the
sendAsynchronousRequest
method will return almost immediately, but the completion handler won't be called until sometime later, after the server responds to the request. So typically the completion handler is used to notify the main thread that the operation has completed. One way to notify the main thread is with code like thiswhere the
someMethod
method is declared asThat way, you can do something with the results after the network request has finished.
There are a couple of issues.
Naming Conventions
Your method
getToken:andPassword:
should be asynchronous.Improper use of
NSOperationQueue
(you don't need that)No Content-Type header specified
Omitting parameter encoding in the Query component of the URI (
x-www-form-urlencoded
)Some lack of experience which
NSURLConnection
:Don't use class convenience methods unless you know exactly that your request works with the implemented default behavior (for requests with authentication this is almost always never the case). Please read the official docs
So, for a solution, I would suggest the delegate approach of either
NSURLConnection
orNSURLSession
. See examples and code snippets in the official docs already mentioned above.You will have to handle an authentication challenge, where you provide the credentials. This also frees you from the error prone and inconvenient need to percent encode the parameters if you would put them into the URL or the body.
You should also use
https
.