I've followed some tutorials, but I'm stuck on doing Post requests. I Just want to send 3 parameters, to a URL and hadle with the response. And it has to be asynchronous, because it will give me some images, that i want to but one by one on the view.
Can you help me guys?
This is well covered here.
But the way I do it I find to be simpler, as I'll show you. Still there are many questions here on SO and other places that provide this knowledge.
First we set up our request with our parameters:
- (NSData *)executePostCall {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#", YOUR_URL]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *requestFields = [NSString stringWithString:#""];
requestFields = [requestFields stringByAppendingFormat:#"parameter1=%#&", parameter1];
requestFields = [requestFields stringByAppendingFormat:#"parameter2=%#&", parameter2];
requestFields = [requestFields stringByAppendingFormat:#"parameter3=%#", parameter3];
requestFields = [requestFields stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *requestData = [requestFields dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestData;
request.HTTPMethod = #"POST";
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error == nil && response.statusCode == 200) {
NSLog(#"%i", response.statusCode);
} else {
//Error handling
}
return responseData;
}
This has to be wrapped up in a block since we can't execute this on the main thread because it will lock up our application and that is frowned upon, so we do the following to wrap this request up, I'll leave the rest of the details up to you:
dispatch_queue_t downloadQueue = dispatch_queue_create("downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *result = [self executePostCall];
dispatch_async(dispatch_get_main_queue(), ^{
// Handle your resulting data
});
});
dispatch_release(downloadQueue);
Use NSURLRequest. You can download files in the background and show them once you receive the delegate notification: Downloading to a Predetermined Destination
Related
I am trying to learn web service on iOS.
I'm starting of from getting an image from a JSON api link.
I've used the code below but the image is not displaying and I'm getting warning that says
Incompatible pointer types assigning to 'UIImage * _Nullable' from 'NSSting * _Nullable'
My code
NSURL *urlAdPop = [NSURL URLWithString:#"JSON LINK HERE"];
NSURLRequest *request = [NSURLRequest requestWithURL:urlAdPop];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary *AdPopUp = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
popUpBanner.image = [[AdPopUp objectForKey:#"ad_image"] stringValue];
popUpAdURL = [AdPopUp objectForKey:#"ad_link"];
}
}];
popUpBanner.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:popUpAdURL]];
popUpBanner.hidden = NO;
popUpBanner.layer.cornerRadius = 9;
popUpBanner.clipsToBounds = YES;
popUpBanner.userInteractionEnabled = YES;
[self.view addSubview:popUpBanner];
You need to write your code inside block after you get response from webservice.
NSURL *urlAdPop = [NSURL URLWithString:#"JSON LINK HERE"];
NSURLRequest *request = [NSURLRequest requestWithURL:urlAdPop];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary *AdPopUp = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
popUpBanner.image = [[AdPopUp objectForKey:#"ad_image"] stringValue];
popUpAdURL = [AdPopUp objectForKey:#"ad_link"];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:popUpAdURL]];
dispatch_async(dispatch_get_main_queue(), ^{ // get main thread to update image
popUpBanner.image= image
popUpBanner.hidden = NO;
popUpBanner.layer.cornerRadius = 9;
popUpBanner.clipsToBounds = YES;
popUpBanner.userInteractionEnabled = YES;
[self.view addSubview:popUpBanner];
});
}
}];
popUpBanner.layer.cornerRadius = 9;
popUpBanner.clipsToBounds = YES;
popUpBanner.userInteractionEnabled = YES;
popUpBanner.hidden = YES;
[self.view addSubview:popUpBanner];
NSString* strURL=#"JSON LINK HERE";
NSString* webStringURL = [strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *urlAdPop = [NSURL URLWithString:webStringURL];
NSURLRequest *request = [NSURLRequest requestWithURL:urlAdPop];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary *AdPopUp = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
popUpAdURL = [AdPopUp objectForKey:#"ad_link"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[AdPopUp objectForKey:#"ad_image"]]]];
if (imgData)
{
UIImage *image = [UIImage imageWithData:imgData];
if (image)
{
dispatch_async(dispatch_get_main_queue(), ^{
popUpBanner.image = image;
popUpBanner.hidden = NO;
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
});
}
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
});
}
});
}
}];
Perfect way to display image!
Hope It will help you :)
If you need to deal with images comes from web response then you can use SDWebImage library from GitHub.
In its read me page they have also provided the way how you can achieve it.
#import <SDWebImage/UIImageView+WebCache.h>
[self.YourImageView sd_setImageWithURL:[NSURL URLWithString:#"http://yourimagePath/.../"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Thats it !
Firstly,check if that url available in browser. If yes,check if your app accept HTTP(not HTTPS). You can set app accept like this:
You are adding popUpBanner in view after getting image from server. so you have to initialize it before in viewdidload and need to set it's frame.
Then set image to popUpBanner from completion handler of web service on main thread. And make sure that you have to set image not image name string!
Below line is wrong, it is trying to set string to imageview which is not possible.
popUpBanner.image = [[AdPopUp objectForKey:#"ad_image"] stringValue];
get image from image url provided by service side and use image name that you get in response.
And make sure that you are getting image object using breakpoint.
Hope this will help :)
###require suppurate api to load image.
want to attach the link and image name together as to reach. thus two strings are needed to store each the api and the image name.###
s=[[mutarray objectAtIndex:index]valueForKey:#"image"];
NSString *f=[NSString stringWithFormat:#"http://iroidtech.com/wecare/uploads/news_events/%#",s];
NSURL *g=[[NSURL alloc]initWithString:f];
data=[NSMutableData dataWithContentsOfURL:g];
self.imgvw.image=[UIImage imageWithData:data];
_descrilbl.text=[[mutarray objectAtIndex:index]valueForKey:#"image"];
I have have some trouble in understanding what is needed to fetch a JSON file with mantle.h from a URL.
Can someone give me an example of how it works?
For example:
-I have a URL www.example.com with a JSONFile as follows:
{
"name": "michael"
}
How could I fetch it?
I use this process for fetching JSON:
NSURL *s = url;//Put your desird url here
NSURLRequest *requestURL = [NSURLRequest requestWithURL:s cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.00];
NSHTTPURLResponse *response;
NSError *error = [[NSError alloc]init];
NSData *apiData = [NSURLConnection sendSynchronousRequest:requestURL returningResponse:&response error:&error];
dictionaryData = [NSJSONSerialization JSONObjectWithData:apiData options:kNilOptions error:&error];
Now the dictionaryData contains your JSON. You can fetch it by:
NSString *name = [dictionaryData valueForKey:#"name"];
And make sure you are making async request. For this put the code within this block:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//Put the code here
});
Hope this helps.. :)
Call it with following method
[super getRequestDataWithURL:urlString
andRequestName:sometext];
You will get response in the following method if successful
- (void)successWithRequest:(AFHTTPRequestOperation *)operation withRespose:(id)responseObject withRequestName:(NSString *)requestName {
NSString *response = operation.responseString;
id jsonObject = [response objectFromJSONString];
if(![super checkforServerRequestFailureErrorMessage:jsonObject]) {
[self.leaderboardProxyDelegate leaderboardListSuccessful:jsonObject];
}
}
You will get dictionary in jsonObject
I need to know something about button and web service ,normally I'm use Uicollectionview for show data from web service by indexPath.item but if I don't use Uicollectionview It's possible? to pass and get data from web service.
Here's code
-(IBAction)ttButton:(id)sender
{
bookName = #"test";
bookVersion = [[bookList objectAtIndex:indexPath.row]bookVersion];// when I use this it's will crash.
_bookPosition = [[bookList objectAtIndex:indexPath.row]bookPosition];
bookId = #"1";
bookPath = #"test001";
pageAmount = 2;
mainMenu = #"test";
// downloadURL = [[bookList objectAtIndex:indexPath.row]downloadURL];
// pageAmount = [[bookList objectAtIndex:indexPath.row]pageAmount]; I want to go like this. but indexPath I can use only in collection view
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *stringURL = [NSString stringWithFormat:#"http://tlf/testdata/webservice/book_extract.php?main_menu=test&language=en&id=%#",(_bookPosition)];
NSURLResponse *response = nil;
NSError *error = nil;
NSURL *url = [NSURL URLWithString:stringURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[self connection:urlConnection didReceiveResponse:response];
[self connection:urlConnection didReceiveData:data];
[db saveAssetVersion:_assetVersion];
if([db isDownloaded:bookId bookVersion:[bookVersion floatValue]]){
[self performSegueWithIdentifier:#"test" sender:self];
}
else{
[self startDownload];
}
});
});
}
Please Advice for any Idea. Thank you very very much.
I dont think you code to get the data is even being called in the case of Button. Anyway, you need to set the delegate of your NSURLConnection class to the class where fetching code is.
Essentially, there is no difference at all using UICollectionView or UIButton. That is just the difference of how user interacts with the system. The code to download and update should be seperate and should be called by both similarly.
I'm working on an iPad app that requests data from a server, changes and submits it, and then re-requests the data from the server, displaying it to the user. The app updates the data just fine (the equivalent web app sees the update happening), but the data that the iPad app gets back is the old data. I thought maybe it was the caching flag on the NSURLRequest, but it doesn't look like it.
Here is my sequence of calls:
NSString* currentStuff = self.fCurrentIndex.currentStuff;
NSError* err = nil;
[self.fCurrentIndex approve:currentStuff withUsername:username andPassword:password error:&err];
if (err == nil)
{
// rebuild the case list (grab the data from the URL again first)
[self getCaseListViaURL]; // grab the updated data
[self setupUIPanel]; // display it
}
Here's the code that grabs the data (the 'getCaseListViaURL' call):
NSURLResponse* response;
NSError* err = nil;
NSMutableDictionary * jsonObject = nil;
NSString * urlRequestString;
urlRequestString = [method to get the URL string];
NSURL * url = [NSURL URLWithString:urlRequestString];
NSURLRequest * request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
NSData * data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&err];
if (err == nil)
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&err];
}
if (err && error) {
*error = err;
}
return jsonObject;
Is there any way to force the server to serve up the updated data?
Thanks in advance.
EDIT: Per comments, I'm adding the sequence of update to the server and subsequent pull:
This does the push to the server:
NSString* currentStuff = self.fCurrentIndex.currentStuff;
NSError* err = nil;
[self.fCurrentPatient approveStuff:currentStuff withUsername:username andPassword:password error:&err];
Where 'approveStuff' eventually calls:
__block NSData * jsonData;
__autoreleasing NSError * localError = nil;
if (!error) {
error = &localError;
}
// Serialize the dictionary into JSON
jsonData = [NSJSONSerialization dataWithJSONObject:data
options:NSJSONWritingPrettyPrinted
error:error];
if (*error) return nil;
NSURLResponse* response;
NSString * urlRequestString;
urlRequestString = [self urlStringForRelativeURL:relativeURL
withQueryParams:params];
NSURL * url = [NSURL URLWithString:urlRequestString];
NSMutableURLRequest * request;
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:self.cachePolicy
timeoutInterval:self.timeOutInterval];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:jsonData];
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
jsonData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&localError];
NSMutableDictionary * jsonObject;
if (localError == nil)
{
jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&localError];
}
if (error && localError) {
*error = localError;
}
return jsonObject;
Right after this, I call the aforementioned get call and rebuild the UI. Now, if I stick a breakpoint when I do the get, and check on the web server if the data is updated after the push, I see the data is there. However, when I let the get operation continue, it gives me the old data.
So it looks like the issue was on the server. There were some data structures on the server side that weren't being refreshed when the data was being posted.
There are, for example, 100 JSON files and appropriate 100 images on my ftp server.
1.With loading JSON where are no bug (I hope)
NSString *recipesPath = #"ftp://.../recipes/";
NSString *recipeFileName = [NSString stringWithFormat:#"00001.json", recipeCode];
NSString *recipeFileFullPath = [recipesPath stringByAppendingString:recipeFileName];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:recipeFileFullPath]];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError *error = nil;
NSDictionary *recipeDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
2.But images can not be loaded
NSString *recipeImageName = #"recipeImages/00001-1.jpg";
NSString *recipeImageFullPath = [recipesPath stringByAppendingString:recipeImageName];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:recipeImageFullPath]];
if (request) {
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (responseData) {
UIImage *image = [UIImage imageWithData:responseData];
}
}
responseData nearly always is nil.
May be there is the other method?
All this code is in MyMethod which I execute in NSOperationQueue:
operation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(MyMethod) object:nil];
[operationQueue addOperation:operation];
EDIT: image sizes are not big - from 50 to 100 kbyte
EDIT: can image file extension affect to downloading process?
You can try this:
NSURL *url = [NSURL URLWithString:recipeImageFullPath];
NSData *data = [NSData alloc] initWithContentsOfURL:url];
Please try to test it:
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
/* Return Value
The downloaded data for the URL request. Returns nil if a connection could not be created or if the download fails.
*/
if (responseData == nil) {
// Check for problems
if (requestError != nil) {
...
}
}
else {
// Data was received.. continue processing
}