Асинхронный вызов с использованием xCode
У меня есть еще один вопрос для начинающих, связанный с xCode. Я совершенно новичок в разработке для iOS, поэтому я благодарен вам, ребята, чтобы ответить мне.
Я написал следующий класс для доступа к Restful API. Код в методе "makePostRequest" работает нормально, если я пишу его непосредственно в вызывающий метод. Но я хочу сделать это асинхронным, и я не знаю точно, как я могу сделать эту работу асинхронной. Может кто-нибудь помочь мне написать это как вызов asynchronos?
#import <Foundation/Foundation.h>
#import "ServerRequest.h"
#import "NetworkHelper.h"
@implementation ServerRequest
@synthesize authorizationRequest=_authorizationRequest;
@synthesize responseContent=_responseContent;
@synthesize errorContent=_errorContent;
@synthesize url=_url;
@synthesize urlPart=_urlPart;
@synthesize token=_token;
- (void)makePostRequest : (NSString *) params {
NSString *urlString = [NSString stringWithFormat:@"%@%@", [self getUrl], [self getUrlPart]];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
if([self isAuthorizationRequest]) {
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"Basic" forHTTPHeaderField:@"Authorization"];
}
else {
NSString *authorizationValue = [NSString stringWithFormat:@"Bearer %@", [self getToken]];
[request setValue:authorizationValue forHTTPHeaderField:@"Authorization"];
}
if(params.length > 0)
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
@try {
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error) {
NSLog(@"Error: %@", error);
}
if([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if(statusCode == [NetworkHelper HTTP_STATUS_CODE]) {
self.responseContent = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:nil];
}
else {
self.errorContent = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:nil];
}
}
}];
[dataTask resume];
}
@catch (NSException *exception) {
NSLog(@"Exception while making request: %@", exception);
} @finally {
NSLog(@"finally block here");
}
}
- (void)setAuthorization : (bool)value {
self.authorizationRequest = &value;
}
- (bool)isAuthorizationRequest {
return self.authorizationRequest;
}
- (NSDictionary *)getResponseContent {
return self.responseContent;
}
- (NSDictionary *)getErrorContent {
return self.errorContent;
}
- (void)setToken:(NSString *)token {
self.token = token;
}
- (NSString *)getToken {
return self.token;
}
- (void)setUrl:(NSString *)value {
//self.url = value;
_url = value;
}
- (NSString *)getUrl {
return self.url;
}
- (void)setUrlPart:(NSString *)value {
self.urlPart = value;
}
- (NSString *)getUrlPart {
if(self.urlPart.length == 0)
return @"";
return self.urlPart;
}
@end
1 ответ
Я приведу вам пример того, как вы можете сделать так, чтобы ваш метод служил вам данными, когда они доступны. Это block
основан. Таким образом, вам не нужно рассматривать асинхронную задачу здесь.
Сначала определите ваш блок завершения в вашем ServerRequest.h
:
typedef void(^myCompletion)(NSDictionary*, NSError*);
И измените подпись вашего метода на это:
- (void) makePostRequest:(NSString *)params completion: (myCompletion)completionBlock;
Теперь измените реализацию вашего метода на что-то вроде этого (я только публикую @try
блок, так что просто измените свой блок try. Остальные остаются такими же)
@try {
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error) {
NSLog(@"Error: %@", error);
if (completionBlock) {
completionBlock(nil, error);
}
}
if([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if(statusCode == [NetworkHelper HTTP_STATUS_CODE]) {
NSError *error;
self.responseContent = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:&error];
if (completionBlock) {
if (error == nil) {
completionBlock(self.responseContent, nil);
} else {
completionBlock(nil, error);
}
}
} else {
NSError *error;
self.errorContent = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
error:&error];
if (completionBlock) {
if (error == nil) {
completionBlock(self.errorContent, nil);
} else {
completionBlock(nil, error);
}
}
}
}
}];
[dataTask resume];
}
Наконец, когда вы вызываете этот метод откуда-то еще, используйте это как:
[serverRequestObject makePostRequest:@"your string" completion:^(NSDictionary *dictionary, NSError *error) {
// when your data is available after NSURLSessionDataTask's job, you will get your data here
if (error != nil) {
// Handle your error
} else {
// Use your dictionary here
}
}];