iOS App在调用方法时等待HTTP响应?

时间:2013-01-07 13:44:20

标签: objective-c ios nsurlconnection

我正在尝试调用一个类方法,该方法接受一个字符串并将其发布到站点以接收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

“收到数据”后,我在日志中没有收到任何数据,也没有看到我的错误消息。谢谢你

3 个答案:

答案 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];