可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'m new to objective-c and I\'m starting to put a great deal of effort into request/response as of recent. I have a working example that can call a url (via http GET) and parse the json returned.
The working example of this is below
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog([NSString stringWithFormat:@\"Connection failed: %@\", [error description]]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
//do something with the json that comes back ... (the fun part)
}
- (void)viewDidLoad
{
[self searchForStuff:@\"iPhone\"];
}
-(void)searchForStuff:(NSString *)text
{
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@\"http://www.whatever.com/json\"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
My first question is - will this approach scale up? Or is this not async (meaning I block the UI thread while the app is waiting for the response)
My second question is - how might I modify the request part of this to do a POST instead of GET? Is it simply to modify the HttpMethod like so?
[request setHTTPMethod:@\"POST\"];
And finally - how do I add a set of json data to this post as a simple string (for example)
{
\"magic\":{
\"real\":true
},
\"options\":{
\"happy\":true,
\"joy\":true,
\"joy2\":true
},
\"key\":\"123\"
}
Thank you in advance
回答1:
Here\'s what I do (please note that the JSON going to my server needs to be a dictionary with one value (another dictionary) for key = question..i.e. {:question => { dictionary } } ):
NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@\"StoreNickName\"],
[[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@\"user_question\"], nil];
NSArray *keys = [NSArray arrayWithObjects:@\"nick_name\", @\"UDID\", @\"user_question\", nil];
NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@\"question\"];
NSString *jsonRequest = [jsonDict JSONRepresentation];
NSLog(@\"jsonRequest is %@\", jsonRequest);
NSURL *url = [NSURL URLWithString:@\"https://xxxxxxx.com/questions\"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:@\"POST\"];
[request setValue:@\"application/json\" forHTTPHeaderField:@\"Accept\"];
[request setValue:@\"application/json\" forHTTPHeaderField:@\"Content-Type\"];
[request setValue:[NSString stringWithFormat:@\"%d\", [requestData length]] forHTTPHeaderField:@\"Content-Length\"];
[request setHTTPBody: requestData];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if (connection) {
receivedData = [[NSMutableData data] retain];
}
The receivedData is then handled by:
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [jsonString JSONValue];
NSDictionary *question = [jsonDict objectForKey:@\"question\"];
This isn\'t 100% clear and will take some re-reading, but everything should be here to get you started. And from what I can tell, this is asynchronous. My UI is not locked up while these calls are made. Hope that helps.
回答2:
I struggled with this for a while. Running PHP on the server. This code will post a json and get the json reply from the server
NSURL *url = [NSURL URLWithString:@\"http://example.co/index.php\"];
NSMutableURLRequest *rq = [NSMutableURLRequest requestWithURL:url];
[rq setHTTPMethod:@\"POST\"];
NSString *post = [NSString stringWithFormat:@\"command1=c1&command2=c2\"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
[rq setHTTPBody:postData];
[rq setValue:@\"application/x-www-form-urlencoded\" forHTTPHeaderField:@\"Content-Type\"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:rq queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if ([data length] > 0 && error == nil){
NSError *parseError = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(@\"Server Response (we want to see a 200 return code) %@\",response);
NSLog(@\"dictionary %@\",dictionary);
}
else if ([data length] == 0 && error == nil){
NSLog(@\"no data returned\");
//no data, but tried
}
else if (error != nil)
{
NSLog(@\"there was a download error\");
//couldn\'t download
}
}];
回答3:
I would suggest to use ASIHTTPRequest
ASIHTTPRequest is an easy to use
wrapper around the CFNetwork API that
makes some of the more tedious aspects
of communicating with web servers
easier. It is written in Objective-C
and works in both Mac OS X and iPhone
applications.
It is suitable performing basic HTTP
requests and interacting with
REST-based services (GET / POST / PUT
/ DELETE). The included
ASIFormDataRequest subclass makes it
easy to submit POST data and files
using multipart/form-data.
Please note, that the original author discontinued with this project. See the followring post for reasons and alternatives: http://allseeing-i.com/%5Brequest_release%5D;
Personally I am a big fan of AFNetworking
回答4:
Most of you already know this by now, but I am posting this, just incase, some of you are still struggling with JSON in iOS6+.
In iOS6 and later, we have the NSJSONSerialization Class that is fast and has no dependency on including \"outside\" libraries.
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
This is the way iOS6 and later can now parse JSON efficiently.The use of SBJson is also pre-ARC implementation and brings with it those issues too if you are working in an ARC environment.
I hope this helps!
回答5:
Here is a great article using Restkit
It explains on serializing nested data into JSON and attaching the data to a HTTP POST request.
回答6:
Since my edit to Mike G\'s answer to modernize the code was rejected 3 to 2 as
This edit was intended to address the author of the post and makes no
sense as an edit. It should have been written as a comment or an
answer
I\'m reposting my edit as a separate answer here. This edit removes the JSONRepresentation
dependency with NSJSONSerialization
as Rob\'s comment with 15 upvotes suggests.
NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@\"StoreNickName\"],
[[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@\"user_question\"], nil];
NSArray *keys = [NSArray arrayWithObjects:@\"nick_name\", @\"UDID\", @\"user_question\", nil];
NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@\"question\"];
NSLog(@\"jsonRequest is %@\", jsonRequest);
NSURL *url = [NSURL URLWithString:@\"https://xxxxxxx.com/questions\"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *requestData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; //TODO handle error
[request setHTTPMethod:@\"POST\"];
[request setValue:@\"application/json\" forHTTPHeaderField:@\"Accept\"];
[request setValue:@\"application/json\" forHTTPHeaderField:@\"Content-Type\"];
[request setValue:[NSString stringWithFormat:@\"%d\", [requestData length]] forHTTPHeaderField:@\"Content-Length\"];
[request setHTTPBody: requestData];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if (connection) {
receivedData = [[NSMutableData data] retain];
}
The receivedData is then handled by:
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *question = [jsonDict objectForKey:@\"question\"];
回答7:
Here\'s an updated example that is using NSURLConnection +sendAsynchronousRequest: (10.7+, iOS 5+), The \"Post\" request remains the same as with the accepted answer and is omitted here for the sake of clarity:
NSURL *apiURL = [NSURL URLWithString:
[NSString stringWithFormat:@\"http://www.myserver.com/api/api.php?request=%@\", @\"someRequest\"]];
NSURLRequest *request = [NSURLRequest requestWithURL:apiURL]; // this is using GET, for POST examples see the other answers here on this page
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if(data.length) {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(responseString && responseString.length) {
NSLog(@\"%@\", responseString);
}
}
}];
回答8:
You can try this code for send json string
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:ARRAY_CONTAIN_JSON_STRING options:NSJSONWritin*emphasized text*gPrettyPrinted error:NULL];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *WS_test = [NSString stringWithFormat:@\"www.test.com?xyz.php¶m=%@\",jsonString];