【问题标题】:Send JSON request with iOS使用 iOS 发送 JSON 请求
【发布时间】:2014-03-29 02:43:38
【问题描述】:

我在尝试使用 iOS 应用程序发送 JSON 请求时遇到问题。 我必须发送这样的东西:

http://url/User/Create/{"newsletter" : 1,"password" : "sdsd", ...}

但在应用上执行此操作时请求无效:

 NSURL   *url = [NSURL URLWithString:@"http://url/User/Create/"];
NSData *jsonData;

NSDictionary *dic = @{
                      @"login" : @"sdsd",
                      @"password" : @"sdsd",
                      @"newsletter" : @1,
                      @"firstname" : @"sdsd",
                      @"lastname" : @"sdsd",
                      @"email" :  @"sdsd@hotmail.fr"};
jsonData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setHTTPBody: jsonData];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];

NSError *errorReturned = nil;
NSURLResponse *theResponse =[[NSURLResponse alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&errorReturned];

如何以有效格式发送请求?

【问题讨论】:

  • 能贴出具体的错误吗?
  • 它不会抛出任何错误,但是当我尝试使用登录名和密码登录时,我得到一个 {"result":"ko"},但是当我尝试注册时它可以工作通过浏览器
  • @Gezurb 检查我的回答。我认为我的回答对你有帮助。
  • @Gezurb 检查我编辑的答案。
  • POST 请求似乎是正确的。尽管如此,当您发送请求时可能会出现一些错误:url 格式错误、服务器已关闭、服务器接受 JSON 但在语义上不理解内容、身份验证失败等。您真的应该在任何时候检查错误可能的!特别是如果服务器返回响应:检查状态码和 MIME 类型!

标签: ios iphone objective-c json


【解决方案1】:
-(void)tryThis  
{  
NSString *a=@"{'login' : 'sdsd', 'password' : 'sdsd', 'newsletter' : 1, 'firstname' : 'sdsd', 'lastname' : 'sdsd',  'email' :  'sdsd@hotmail.fr'}";    
a= [a stringByReplacingOccurrencesOfString:@"'" withString:@"\"" options:NSCaseInsensitiveSearch range:NSMakeRange (0, [a length])];  
NSData* postData= [a dataUsingEncoding:NSUTF8StringEncoding];  
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https:***********your url"]];  
[request setHTTPMethod:@"POST"];  
[request setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];  
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];   
[request setHTTPBody:postData];  
NSURLResponse *response = NULL;   
NSError *requestError = NULL;   
NSData *responseData1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&requestError];   
NSString *responseString = [[NSString alloc] initWithData:responseData1 encoding:NSUTF8StringEncoding];   
 }  

【讨论】:

  • 你为什么建议使用一种不可靠的方法来构造 JSON - 而不是使用 NSJSONSerialization 来完成这项工作?
  • 我遇到了和他现在一样的问题,这解决了我的问题,我认为这会有所帮助。
  • 那么,你是说NSJSONSerialization 有问题?
  • 不,有时我们的编码格式取决于服务器端代码(他们如何编码) NSJSONSerialization 很好,我在近 38 个应用程序中使用了它,但是当 NSJSONSerialization 完成时,上面的代码是唯一对我有用的代码工作(正如我所说的取决于我们需要编码的服务器端请求)
  • 但您确实将 application/json 指定为内容类型。从兼容 JSON 的 NSDictionary 或 NSArray 获取字节序列(内容为 UTF-8 的 NSData)的最简单方法是使用 NSJSONSerialization。所以,我不明白你的方法,即使你断言 NSJSONSerialization 是正确的。注意:可能添加一个字符集参数,例如:application/json; charset=utf-8 可能会修复 your 问题,如果服务器无法从给定的 JSON 中推断出编码 - 但通常它应该.
【解决方案2】:

HttpRequestSenderDelegate.h

@protocol HttpRequestSenderDelegate <NSObject>

-(void) didFinishLoading:(BOOL)success data:(NSData*)data;

@end

HttpPostRequestSender.h

@protocol HttpRequestSenderDelegate;
@interface HttpPostRequestSender : NSObject

- (id)initWithDelegate:(id<HttpRequestSenderDelegate>) delegate;
- (void)send:(NSString*)url postParams:(NSString*)postParams;
- (void)cancelDownload;

@end

HttpPostRequestSender.m

#import "HttpPostRequestSender.h"
        #import "HttpRequestSenderDelegate.h"

        @interface HttpPostRequestSender ()
        @property (nonatomic, weak) id<HttpRequestSenderDelegate> delegate;
        @property (nonatomic, strong) NSMutableData *activeDownload;
        @property (nonatomic, strong) NSURLConnection *dataConnection;
        @end

        @implementation HttpPostRequestSender
        @synthesize delegate = _delegate,
                    activeDownload = _activeDownload,
                    dataConnection = _dataConnection;

        - (id)initWithDelegate:(id<HttpRequestSenderDelegate>) delegate
        {
            self = [super init];
            if (self) {
                self.delegate = delegate;
            }
            return self;
        }

        - (void)cancelDownload
        {
            [self.dataConnection cancel];
            self.dataConnection = nil;
            self.activeDownload = nil;
        }

        - (void)send:(NSString*)url postParams:(NSString*)postParams
        {
            NSURL *nsurl = [NSURL URLWithString:url];
            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsurl
                                                                   cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                               timeoutInterval:60.0];
            [request setHTTPMethod:@"POST"];
            [request setHTTPBody:[postParams dataUsingEncoding:NSUTF8StringEncoding]];
            NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
            self.dataConnection = conn;

        }

        - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
        {
            self.activeDownload = [[NSMutableData alloc] init];
        }

        - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
        {
            [self.activeDownload appendData:data];
        }

        - (void)connectionDidFinishLoading:(NSURLConnection *)connection
        {
            [self.delegate didFinishLoading:YES data:self.activeDownload];
            self.dataConnection = nil;
            self.activeDownload = nil;
        }

        - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
        {
            UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"The download could not complete - please make sure you're connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
            [errorView show];
            [self.delegate didFinishLoading:NO data:nil];
            self.dataConnection = nil;
            self.activeDownload = nil;
        }

        @end

在您的视图控制器中:MyViewController.h

#import <UIKit/UIKit.h>
#import "HttpRequestSenderDelegate.h"

    @interface MyViewController : UIViewController <HttpRequestSenderDelegate>
    @end

MyViewController.m

    #import "MyViewController.h"
        #import "HttpPostRequestSender.h"


        @interface MyViewController ()
        @property (nonatomic, strong) HttpPostRequestSender *requestSender;
        @end

        @implementation MyViewController
        @synthesize requestSender = _requestSender;

    -(HttpPostRequestSender*) requestSender
    {
        if(_requestSender == nil) _requestSender = [[HttpPostRequestSender alloc] initWithDelegate:self];
        return _requestSender;
    }

- (void)viewDidLoad
{
     //for example i send the request in the view did load

     [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
     NSString *url = @"your url";
     //post params
     NSString *postParams =@"login=sdsd&password=sdsd&email=sdsd@hotmail.fr";
     [self.requestSender send:url postParams:postParams];
}           

- (void) didFinishLoading:(BOOL)success data:(NSData *)data
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    if(success && data != nil) {
          //here you can parse the response
    }
}

@end

【讨论】:

    猜你喜欢
    • 2013-02-27
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    • 2011-09-25
    • 2014-06-25
    • 1970-01-01
    相关资源
    最近更新 更多