使用 xCode 的异步调用

Asynchronous call using xCode

我还有一个与 xCode 有关的初学者问题。我对 iOS 开发完全陌生,所以非常感谢你们回复我。

我写了下面的 class 来访问 Restful API。如果我直接在调用方法中编写方法 "makePostRequest" 中的代码,则可以正常工作。但是,我想让它异步,但我不知道如何才能使它异步。有人可以帮我把它写成异步调用吗?

#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

我正在举例说明如何让您的方法在可用时为您提供数据。它基于 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
    }
}];