我正在尝试调用一个类方法,该方法接受一个字符串并将其发布到站点以接收JSON响应(在我存储在DataClass中的一些其他变量中)。我试图以响应的形式返回数据,并且此时甚至不能NSLog返回的数据。问题是,现在我调用了我的类方法,类方法如何等待从HTTP POST返回响应以返回数据?一旦我返回我的JSON,我就可以将它扩展为字典并从那里开始处理。感谢帮助:)
班级方法:
//
// APISample.m
//
// Created by Sam on 1/6/13.
// Copyright (c) 2013 Sam. All rights reserved.
//
#import "APISample.h"
#import "DataClass.h"
@implementation APISample
@synthesize first_name = _first_name;
@synthesize last_name = _last_name;
@synthesize profile_pic_url = _profile_pic_url;
@synthesize responseData;
-(id)init
{
self = [super init];
return self;
NSLog(@"Loaded APISample and fetching");
}
+(id)getDataAboutUser:(NSString *)user_request_id;
{
DataClass *userdata=[DataClass getInstance];
NSLog(@"Loaded APISample and fetching %@", user_request_id);
NSMutableURLRequest *user_fetch_details = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://10.0.23.161/users/user_fetch_details.php"]];
[user_fetch_details setHTTPMethod:@"POST"];
NSMutableString *postString = [NSMutableString stringWithString:@"id=123"];
[postString appendString:@"&userrequest_id="];
[postString appendString:[userdata.str_userid copy]];
[postString appendString:@"&user_id="];
[postString appendString:[userdata.str_userid copy]];
[postString appendString:@"&identifier="];
[postString appendString:[userdata.str_identifier copy]];
[user_fetch_details setValue:[NSString stringWithFormat:@"%d", [postString length]] forHTTPHeaderField:@"Content-length"];
[user_fetch_details setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:user_fetch_details delegate:self];
NSMutableData *responseData=[NSMutableData data];
[responseData appendData:[NSURLConnection connection:didReceiveData];
if (connection) {
// Create the NSMutableData that will hold
// the received data
// receivedData is declared as a method instance elsewhere
NSMutableData *responseData=[NSMutableData data];
} else {
// inform the user that the download could not be made
}
NSLog(@"Received Data %@", [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding]);
return [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
NSString *receivedDataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ([receivedDataString isEqualToString: @"error"]) {
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"An error has occured. The application will now exit. Unexpected Response!"
delegate:nil
cancelButtonTitle:@"Close"
otherButtonTitles:nil];
[errorAlert show];
exit(0);
}else{
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSString *firstnameResponse = [json objectForKey:@"first_name"];
NSString *lastnameResponse = [json objectForKey:@"last_name"];
NSString *profile_pic_urlResponse = [json objectForKey:@"profile_pic_url"];
NSLog(@"didReceiveData %@ analysed " , firstnameResponse);
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading");
NSLog(@"Succeeded! Received %d bytes of data",[self.responseData length]);
}
@end
“收到数据”后,我在日志中没有收到任何数据,也没有看到我的错误消息。谢谢你
答案 0 :(得分:3)
您描述的设计模式称为CallBack。您需要收到有关未来某个时间点发生的事件的通知。在objective-c中有4种主要形式的回调。
目标行动配对(这是按钮和类似的东西。“按下此按钮时,通知我的目标,并告诉他们执行此动作“)
代表团(你在NSURLConnection上面的代码中使用了一种委托形式。当你看到'委托'这个词时,我想让你想'辅助对象'。你说,“嘿NSURLConnection,当重要事件发生时,我希望你告诉这个委托(帮助对象)关于这些事件)
通知(在处理模型对象更改时会大量使用这些通知)
最后......我会为你的目的推荐的那个......
块。
一个块是一个非常酷的变量。大多数变量都包含数据块是一个变量,它保存将来某个时刻执行的代码。因此,在您的情况下,您可以传递一个完成块以及您的方法getDataAboutUser:(NSString *)user_request_id。所以它看起来像这样。
getDataAboutUser:(NSString *)string withCompletion:(void(^)(NSData * finishedData))cBlock
将cBlock存储为instanceVar。然后,当NSURLConnection完成下载其所有数据时,您将执行cBlock,将完成的数据作为参数传递。
如果您之前没有使用过积木是一件相当复杂的事情,那么我建议您花20分钟时间阅读this。
答案 1 :(得分:1)
由于您需要在返回之前等待响应的方法,因此可以使用NSURLConnection的便捷类方法sendSynchronousRequest来执行同步请求,而不是异步创建和管理NSURLConnection实例。
因此,您可以执行此操作,而不是您的[[NSURLConnection alloc] init ...]行:
NSURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:user_fetch_details returningResponse:&response error:&error];
之后,您可以立即解析来自responseData的JSON,而不是在连接中执行该操作:didReceiveData委托。
编辑:刚看到user698846建议修改方法签名以获取完成块。如果您可以自由地更改方法签名(即没有人要求您的函数同步返回),那么这也是解决问题的好方法。无论哪种方式,sendSynchronousRequest可能是最简单的方法,并且没有任何耻辱,特别是如果你的应用程序没有没有,你的用户可以在等待请求完成时做。
答案 2 :(得分:0)
这是一些代码:
NSURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:user_fetch_details returningResponse:&response error:&error];