Downloading images and captions with JSON in xcode - objective-c

I have googled this numerous times, with lots of different phrasing, but nothing seems to have exactly what I am after.
What I want to do is to download images and captions into a NSArray with JSON. I do not want to save these images, only display them in a UICollectionView. It would be much easier to be able to download multiple images using the same URL, not just 1 image per URL.
Since I am a fairly newbie programmer, I only know how to use NSURLRequest. This is some of my code:
NSString *getDataURL = [[NSString stringWithFormat:#"URL and a couple of perams", var, var2] stringByReplacingOccurencesOfString:#" " withString:#"%20"];
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:getDataURL]];
[[NSURLConnection alloc] initWithRequest:req delegate:self];
And then a bit later on in the connectionDidFinishLoading: method:
NSArray *dataArray = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil]; // variable 'data' is an NSMutableData declared in .h
Please advise on what to do, or even if it's possible!
Thanks in advance!

You can do it this way:
-(void) loadImageAtURL:(NSString*)url {
NSURL *requestURL = [[NSURL alloc] initWithString:url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:requestURL cachePolicy:nil timeoutInterval:45.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
imageData = [[[NSMutableData alloc] init] retain];
}
And handle response in NSURL delegate methods like:
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data {
[imageData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection {
// RELEASE THE CONNECTION
[connection release];
// CREATE NEW UIIMAGE FROM THE DATA
UIImage *image = [[[UIImage alloc] initWithData:imageData] retain];
[imageData release];
[yourImageView setImage:image];
[image release];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error {
// Handle error
}
Hope these methods will give you direction how to carry out things. You make the JSON handling as per your API response in didReceiveData:(NSData *)data and use that data later in connectionDidFinishLoading:

I'm not sure I understand exactly what you are trying to ask but if your goal is to get a list of images/captions using JSON give AFNetworking a try
https://github.com/AFNetworking/AFNetworking

Related

Cannot call method in objective c

I'm having difficulty understanding how to call a method. Here's the code:
- (void)beachJSON
{
// Build the string to call Beach API
NSString *urlString = [NSString stringWithFormat:#"http://nrw-bwq-dev-api.azurewebsites.net/api/Pull"];
// Create NSURL string from formatted string
NSURL *url = [NSURL URLWithString:urlString];
// Setup and start async download
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
results = [jsonString JSONValue];
}
- (NSArray *)getBeachList {
[self beachJSON];
return results;
}
I call getBeachList from another class to populate 'results', beachJSON is called fine but I need to call
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
Within
- (NSArray *)getBeachList
i.e. right here
- (NSArray *)getBeachList {
[self beachJSON];
//This is where I want to call it to populate results before it is returned
return results;
}
Calling getBeachList will call beachJSON but the connection method will be skipped over leaving 'results' nil
If i try simply putting
[self connection:(NSURLConnection *)connection didReceiveData:(NSData *)data]
I get a expected expression error on that line.
I'm pretty new to objective c so any help would be great.
You don't need to call this method.
It's a delegate method of NSURLConnection.
What you need is to set a delegate for connection and method will be called by connection when it downloads any data.
You should not call connection:didReceiveData: by yourself. This is an event which is only supposed to be fired by the NSURLConnection instance. As far as I can see the only thing you are missing is the start call, which actually makes the NSURLConnection perform the request.
Try this:
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
Then you should see that your NSURLConnection instance will call your implementation of connection:didReceiveData:.
If you want to be sure that your data is fully loaded you should be using this event instead:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
The connection:didReceiveData: will be called multiple times if your data size is large enough. Every time the NSURLConnection receives data it will invoke connection:didReceiveData:. connectionDidFinishLoading: will only be called once when all your data is ready.

Making TableView Pull from 1 of 2 NSURLRequests

I am having trouble telling my table view which NSURLRequest it should target. I can get a basic table view to load with a single query, but am trying to make it pull the json string from a different URL if certain segmented controls are active.
These first three lines of code work by themselves
NSString *urlA1 = [NSString stringWithFormat:#"http://www.website.com/json_books.php?
item_id=%#",itemId];
NSURL *urlA2 = [NSURL URLWithString:urlA1];
NSURLRequest *requestA = [NSURLRequest requestWithURL:urlA2];
[[NSURLConnection alloc] initWithRequest:requestA delegate:self];
However, if I include the following three lines after the first three, the tableview loads the json from the first NSURLRequest, then immediately flickers and shows content from the string below:
NSString *urlB1 = [NSString stringWithFormat:#"http://www.website.com/json_movies.php?
item_id=%#",itemId];
NSURL *urlB2 = [NSURL URLWithString:urlB1];
NSURLRequest *requestB = [NSURLRequest requestWithURL:urlB2];
[[NSURLConnection alloc] initWithRequest:requestB delegate:self];
I am pulling the result into the table view with these lines of code:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse
*)response
{
data = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[data appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
items = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
[mainTableView reloadData];
}
Does anyone know why I am unable to specify which NSURLRequest I would like the tableview to target? Thank you!
Do you Want to Show Data from Both The URL ?
if yes then You have to take NSMUtableArray and initialize the Array in ViewDidload before Firing the Request. And You have to Add the Objects into the Array from Each URL.
Example:
[DataArray addObject:#"Yourdata"];
[Yourtable reloadData];
If You need to Separate the data as per Segmented Control then Save Your data in Separate Array.
MyfirstArray= #"Data from URL 1";
MySecondArray= #"Data from URL 2";
-(IBAction)SegmentChange:(Id)sender
{
if(segmented.selectedSegmentIndex==0)
{
items=MyfirstArray;
[mytable reloadData];
}
else
{
items=MysecondtArray;
[mytable reloadData];
}
}
Also You can take Switch statement.

How to get an array from NSMutableData

I have text file with 5 strings. I need to use NSURLConnection to get contnent of this file. But NSLog shows me, that 'dump' is empty. How can I transform the data from NSMutableData to NSArray. Arrays is because I need to show those 5 items in a TableView.
NSURLRequest *theRequest=[NSURLRequest
requestWithURL:[NSURL URLWithString:#"http://dl.dropbox.com/u/25105800/names.txt"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
receivedData = [NSMutableData data];
NSString *dump = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", dump);
NSArray *outputArray=[dump componentsSeparatedByString:#"\n"];
self.namesArray = outputArray;
Thanks in advance. BTW URL works, you can see the file.
Here's how you implement this solution with a delegate:
In your .h file:
#interface MyClass : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
#property (nonatomic, retain) NSMutableData *receivedData;
#property (nonatomic, retain) NSArray *namesArray;
#end
In you .m file:
#implementation MyClass
#synthesize receivedData = _receivedData;
#synthesize namesArray = _namesArray;
- (id)init {
self = [super init];
if (self) {
self.receivedData = [NSMutableData data];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://dl.dropbox.com/u/25105800/names.txt"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
[connection start];
}
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Received response! %#", response);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *dump = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", dump);
self.namesArray = [dump componentsSeparatedByString:#"\n"];
}
#end
If you don't want to use a delegate, you can use a synchronous call with NSURLConnection, like this:
NSURLRequest *theRequest=[NSURLRequest
requestWithURL:[NSURL URLWithString:#"http://dl.dropbox.com/u/25105800/names.txt"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:theRequest response:&response error:&error];
if (error == nil) {
NSString *dump = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", dump);
NSArray *outputArray=[dump componentsSeparatedByString:#"\n"];
self.namesArray = outputArray;
}
Just beware that this will not be running asynchronously. If you don't want it to run on the main thread and block your main thread/UI, consider using a separate thread to execute that code or use GCD.
You have to use the delegate, then save the received data into receivedData (which is of course empty right now.. you just initalized it.) and then you transform the data into a string, like you did it in your example. Have a look at NSURLConnectionDelegate
You need to implement the delegate methods for NSURLConnection to be notified of incoming data. You are using the asynchronous methods.
Also note that [NSMutableData data] just creates an empty data-object.. so you can't expect it to contain any data..
I suggest you read https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html#//apple_ref/doc/uid/20001836-BAJEAIEE
(completely!)

iOS Get Connection

This is my first time on this site and I am very new to coding so I was wondering if somebody could help me out.
I want to set a get request from my iphone app to my website and get the information echoed back from the website to my phone.
I have gotten this far but do not know where to go from here. Any help would be much appreciated, thanks!
- (void)myData:(id)sender
{
NSString *DataToBeSent;
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
[receivedData release];
receivedData = [[NSMutableData alloc] init];
DataToBeSent = [[NSString alloc] initWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php?Data=%#",sender];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
[request setHTTPMethod: #"GET"];
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
[dataToBeSent release];
}
OLD WAY
- (void)myData:(id)sender
{
NSString *dataToBeSent;
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
[receivedData release];
receivedData= [[NSMutableData alloc] init];
dataToBeSent= [[NSString alloc] initWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php?Data=%#",sender];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent]];
Theconn= [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
NSLog (#"test1 %#", theRequest);
NSLog (#"test2 %#", Theconn);
[dataToBeSent release];
}
Then the following methods are called and I get my data BUT if I sent another request after my first one but different data on the same connection, it would always give me the same result which shouldn't happen
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
/* appends the new data to the received data */
[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
NSString *stringData= [[NSString alloc]
initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"Got data? %#", stringData);
[self displayAlertCode:stringData];
[stringData release];
// Do unbelievably cool stuff here //
}
Assuming your data loaded properly you can convert the data into a string and do whatever you want with it.
NSData *response1 = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
//Make sure to set the correct encoding
NSString* responseString = [[NSString alloc] initWithData:response1 encoding:NSASCIIStringEncoding];
If your server returns JSON there are 3rd party libraries that can parse the string into collections like NSArray and NSDictionary. If your server returns XML then NSXMLParser could be something you can use.
EDIT
I've changed your code to manage the memory a little differently.
.h
#property (nonatomic,retain) NSMutableData * receivedData;
#property (nonatomic,retain) NSURLConnection * Theconn;
.m
#synthesize receivedData;
#synthesize Theconn;
//A bunch of cool stuff
- (void)myData:(id)sender
{
//If you already have a connection running stop the existing one
if(self.Theconn != nil){
[self.Theconn cancel];
}
sender = [sender stringByReplacingOccurrencesOfString:#"," withString:#"%20"];
//This will release your old receivedData and give you a new one
self.receivedData = [[[NSMutableData alloc] init] autorelease];
NSString *dataToBeSent = [NSString stringWithFormat:#"http://194.128.xx.xxx/doCalc/getInfo.php? Data=%#",sender];
NSURLRequest *theRequest= [NSURLRequest requestWithURL:[NSURL URLWithString:dataToBeSent]];
//This will release your old NSURLConnection and give you a new one
self.Theconn = [NSURLConnection connectionWithRequest:theRequest delegate:self];
NSLog (#"test1 %#", theRequest);
NSLog (#"test2 %#", Theconn);
}
//...
//Your delegate methods
//...
- (void) dealloc{
[receivedData release];
[Theconn release];
[super dealloc];
}

Objective-C Asynchronous Web Request with Cookies

I am writing a program in Objective-C and I need to make web requests to web server, but asynchronously and I am fairly new on mac, I am very good at windows technologies, but I need to know that if I use NSOperation (introduced in 10.5, i am assuming that it will not run in 10.4 MAC?), or if it was implemented such that it utilizes system threading which will be available on 10.4?
Or I should create a new thread and create a new runloop, also how to use cookies etc, if anyone can give me one small example, that will be of great help. I want this sample to run on mac 10.4 too if possible.
There's a good example of using NSURLRequest and NSHTTPCookies to do a full web application example of logging into a website, storing the SessionID cookie and resubmitting it in future requests.
NSURLConnection, NSHTTPCookie
By logix812:
NSHTTPURLResponse * response;
NSError * error;
NSMutableURLRequest * request;
request = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://temp/gomh/authenticate.py?setCookie=1"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60] autorelease];
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"RESPONSE HEADERS: \n%#", [response allHeaderFields]);
// If you want to get all of the cookies:
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[NSURL URLWithString:#"http://temp"]];
NSLog(#"How many Cookies: %d", all.count);
// Store the cookies:
// NSHTTPCookieStorage is a Singleton.
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:all forURL:[NSURL URLWithString:#"http://temp"] mainDocumentURL:nil];
// Now we can print all of the cookies we have:
for (NSHTTPCookie *cookie in all)
NSLog(#"Name: %# : Value: %#, Expires: %#", cookie.name, cookie.value, cookie.expiresDate);
// Now lets go back the other way. We want the server to know we have some cookies available:
// this availableCookies array is going to be the same as the 'all' array above. We could
// have just used the 'all' array, but this shows you how to get the cookies back from the singleton.
NSArray * availableCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:#"http://temp"]];
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:availableCookies];
// we are just recycling the original request
[request setAllHTTPHeaderFields:headers];
request.URL = [NSURL URLWithString:#"http://temp/gomh/authenticate.py"];
error = nil;
response = nil;
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"The server saw:\n%#", [[[NSString alloc] initWithData:data encoding: NSASCIIStringEncoding] autorelease]);
For asynchronous requests, you need to use NSURLConnection.
For cookies, see NSHTTPCookie and NSHTTPCookieStorage.
UPDATE:
The code below is real, working code from one of my applications. responseData is defined as NSMutableData* in the class interface.
- (void)load {
NSURL *myURL = [NSURL URLWithString:#"http://stackoverflow.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:myURL
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[responseData release];
[connection release];
// Show error message
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Use responseData
[responseData release];
[connection release];
}
I am able to fetch cookie in such way:
NSArray* arr = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString: #"http://google.com" ]];
This one works fine for asynchronous request as well.