我已经创建了一个使用AFNetworking API返回JSON数据的自定义方法。
我试图将从我的Web服务中提取的数据存储在一个数组中作为JSON。 NSLog(@"%@",json);块内部将JSON数据打印到控制台。在块NSLog之外(@"%@",json);返回null。为什么这个以及如何解决?
我尝试做的是让方法返回JSON数据(NSArray)
#import "WebService.h"
#import "AFNetworking.h"
#import "MBProgressHUD.h"
@implementation WebService
- (NSArray *)postRequest:(NSDictionary *)postParameters {
//MBProgressHUD *progressHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
//progressHUD.labelText = @"Loading";
__block NSArray *json;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *responseString = [operation responseString];
NSError *error;
json = [NSJSONSerialization
JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding]
options:kNilOptions
error:&error];
NSLog(@"%@", json); // RETURNS JSON
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable"
message:@"Unable to contact server. Please try again later."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
NSLog(@"Error: %@", error);
}];
NSLog(@"%@", json); // RETURNS NULL
return json;
}
@end
答案 0 :(得分:2)
POST
方法是异步的。意味着该块进入单独的线程并等待执行。虽然这是在后台,但其余的代码仍在继续,好像什么也没发生。所以它立即转到NSLog
语句(可能在你开始POST
请求之前)。
如果您希望json
对象位于您的区块之外,您将不得不从区块内部发送到您选择的方法并继续在那里进行操作。
[manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *responseString = [operation responseString];
NSError *error;
json = [NSJSONSerialization
JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding]
options:kNilOptions
error:&error];
NSLog(@"%@", json); // RETURNS JSON
dispatch_async(dispatch_get_main_queue(), ^{
[self doSomethingWithJson:json];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable"
message:@"Unable to contact server. Please try again later."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
NSLog(@"Error: %@", error);
}];
答案 1 :(得分:2)
由于POST
异步运行,因此无法返回结果。但是您可以使用与AFNetworking相同的完成块模式:
- (void) postRequest:(NSDictionary *)postParameters success:(void (^)(id jsonObject))success failure:(void (^)(NSError *error))failure {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
if (success)
success(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable"
message:@"Unable to contact server. Please try again later."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
if (failure)
failure(error);
}];
}
你称之为:
[self postRequest:postParameters success:^(id jsonObject) {
NSLog(@"json = %@", jsonObject);
} failure:^(NSError *error) {
NSLog(@"error = %@", error);
}];
注意,我已经大大简化了代码,因为您不必执行JSON解析,因为AFNetworking已经为您执行了此操作(因为默认的responseSerializer
是AFJSONResponseSerializer
)。正如您所看到的,上述方法所做的工作并不比标准AFNetworking POST
方法做得多,如果出现错误,该方法会显示UIAlertView
。
答案 2 :(得分:1)
除了wat @ Putz1103说,你可以使用回调方法,这也是一种在JavaScript中使用的技术。
示例:
[manager POST:@"http://192.168.0.100/app.php" parameters:postParameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *responseString = [operation responseString];
NSError *error;
json = [NSJSONSerialization
JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding]
options:kNilOptions
error:&error];
NSLog(@"%@", json); // RETURNS JSON
[self dataRetrievedWithData:json];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Unavailable"
message:@"Unable to contact server. Please try again later."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
NSLog(@"Error: %@", error);
}];
然后你会有一个方法:
- (void)dataRetrievedWithData:(id)data
{
NSLog(@"Here's the data.. do what you want to do with the data here. %@", data);
}
在最后一个方法中,您可以添加逻辑以在请求成功完成时执行。从块返回是不可行的,因为块是在一个单独的线程上执行的。
操作是异步的,这意味着您可以在响应到达后简单地打印出来。异步意味着它在一个单独的线程中运行,因此您必须在响应之前等待响应。