I have a simple json file on http://img.soulapp.cn/appips.json. I test it on Postman, the time is about 200ms.
I tried
NSLog(#"%f",[[NSDate date] timeIntervalSince1970]);
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://img.soulapp.cn/appips.json"]];
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%f",[[NSDate date] timeIntervalSince1970]);
}];
time is 4s.
I tried
[NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://img.soulapp.cn/appips.json"] encoding:NSUTF8StringEncoding error:nil]
time is 200ms.
Why NSURLConnection is slower than stringWithContentsOfURL?
How to improve it or can i make stringWithContentsOfURL safer because it's synchronize method?
Related
//Below is the code i have used to perform simple httpPOST. But app hangs on App launch on splash screen and crashes . i am doing an API Call on applaunch in Appdelegate
- (NSDictionary *)postUserRegWithUrl:(NSString *)urlString andParams:(NSString *)paramString{
NSString * encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)paramString,
NULL,
(CFStringRef)#"+",
kCFStringEncodingUTF8 ));
NSDictionary *responseDictionary;
NSError *err;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",kBaseProdURL,urlString]]];
NSData *data = [encodedString dataUsingEncoding:NSUTF8StringEncoding];
[request setTimeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSLog(#"the data Details is =%#", request);
NSURLResponse *response;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *resSrt = [[NSString alloc]initWithData:responseData encoding:NSASCIIStringEncoding];
NSLog(#"got response==%#", resSrt);
if(resSrt.length)
{
responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&err];
NSLog(#"Response dictionary formed is =%#", responseDictionary);
} else {
NSLog(#"failed to connect");
[self showAlertViewTitle:#"Please try later" withMessage:#"Something went wrong"];
}
return responseDictionary;
}
You shouldn't execute your network calls synchronously, especially on main thread. Either use sendAsynchronousRequest or just use any good networking library, like AFNetworking, which do this out of the box.
First set the timeoutInterval for your request. if your request takes more time then you have to stop the api call and inform the user with proper error message.
For example:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:1200.0];
Don't use Synchronised Request. It will block your main thread.
If your network is slow or server is not responding then your app will take more time to load. Which is not good for the user experience.
Remember, your app’s load time is your first chance to impress your users.
Use Asynchronised Request of the NSURLConnection. Handle the response in the api completion block.
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSString *resSrt = [[NSString alloc]initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"got response==%#", resSrt);
if(resSrt.length)
{
responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&err];
NSLog(#"Response dictionary formed is =%#", responseDictionary);
} else {
NSLog(#"failed to connect");
}
}];
Change queue:[NSOperationQueue mainQueue] parameter based on your need.
queue -> An NSOperationQueue upon which the handler block will
be dispatched.
I am trying to get the number of twitter followers in my iOS App.
I find some Documentation regarding this issue:
https://dev.twitter.com/rest/reference/get/users/lookup
This is the code I have so far:
NSString *apiURLString = [NSString stringWithFormat:#"https://api.twitter.com/1.1/users/lookup.json?screen_name=%#", #"barackobama"];
NSURL *apiURL = [NSURL URLWithString:apiURLString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:apiURL];
request.HTTPMethod = #"GET";
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// ((NSHTTPURLResponse *)response).statusCode
NSLog(#"response = %#", response);
}];
However, I am pretty confused as how to send all the other parameters required for the request.
Thanks in advance!
I am using google places api to get that place's photo but i am unable to locate "photo_reference" field in the returned JSON. Here is what i have done so far.
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/details/json?placeid=%#&key=%#",placeId,appKey];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue new] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) {
NSLog(#"Got Place Details");
NSDictionary *details = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSString *photo_reference = [[[[details valueForKey:#"result"] valueForKey:#"photos"] objectAtIndex:0] valueForKey:#"photo_reference"];
NSLog(#"");
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/photo?maxwidth=302&maxheight=275&photoreference=%#&key=%#",photo_reference,appKey];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue new] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(#"Inner Request");
if (!connectionError) {
}];
}
}];
Places API documentation says that photo_reference could either be found from "Place Search" or "Place Details" requests. I got it from none.
I requested place details using place_id but the json doesnt have any "photos" key.
Same issue here
https://stackoverflow.com/questions/28317739/places-api-dont-retrieve-photos-on-detailed-petition-since-yesterday
Something change since yesterday but I don't know what or why.
EDIT: Today it's working again, maybe some random error from google.
i want to use async req to get json data, i am doing this by syncrouns already, but now requirement is change, but i am unable to modify this code to aync, beacuse i have to return NSdata
+ (NSString *)stringWithUrl:(NSURL *)url
{
// if(kShowLog)
NSLog(#"%#", url);
NSURL *newURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#",url]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:newURL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:1];
// Fetch the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
// NSOperationQueue *opQueue;
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
}
call stringWithUrl on a 2. thread if you want to keep returning the data. (I'd go with async data
dispatch_async(dispatch_get_global_queue(), ^{
NSData *d = [self stringWithUrl:myURL];
...
//update ui
dispatch_sync(dispatch_get_main_queue(), ^{
...
});
});
a way that would work but is QUITE the hack (which apple employed in older APIs on the mac all the time) would be to run the runloop while waiting:
hackisch :: but wraps async in sync given the completion block runs on the same thread then the runloop
__block NSString *responseString = nil;
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:myurl]
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
responseString = [[NSString alloc] initWithData:Data encoding:NSUTF8StringEncoding];
if(!responseString) {
responseString = #"";
}
}];
while(!responseString) {
[NSRunloop currentRunloop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1];
}
return responseString;
You have to create a separate thread for this process, Synchronous call of getting json data will block your main thread.
I'm changing your code to do asynchronous operation for getting json data from web service.
+ (void)stringWithUrl:(NSURL *)url
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
// if(kShowLog)
NSLog(#"%#", url);
NSURL *newURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#",url]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:newURL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:1];
// Fetch the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
// NSOperationQueue *opQueue;
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
dispatch_sync(dispatch_get_main_queue(), ^{
//Here you have to put your code, which you wanted to get executed after your data successfully retrived.
//This block will get executed after your request data load to urlData.
});
});
}
What's wrong with the Asynchronous then,
NSString *responseString;
NSOperationQueue *operation = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:request queue:operation completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(#"data %#", data);
responseString = [[NSString alloc] initWithData:Data encoding:NSUTF8StringEncoding];
}];
return responseString;
I'm just doing exactly what I do for HTTP requests:
NSString *urlStrig = [NSString stringWithFormat:#"https://mysite.com/search.json?param1=10¶m2=String¶m3=20"];
NSURL *url = [NSURL URLWithString:urlStrig];
NSOperationQueue *queue = [NSOperationQueue new];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:Timeout];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"URL:%#\nResponse: %#\nStatusCode: %i\nError: %#", url, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding], ((NSHTTPURLResponse *)response).statusCode, error);
}];
But all I got is a 403 status code everytime. Testing it via curl in the terminal works fine.
Is there any problem between HTTPS and NSURLConnection?