Create a view based application. Name it WebServices. We don't need a nib file for our table view, so dont add one. (I started with the table view, the middle picture, and I didn't create a nib). We would, however need to add two more view controllers later which would need nibs.
Edit WebServicesViewController.h
All we did was to create our model. Anyway lets edit the WebServicesViewController.m
Near the import section add these:
The define statements just creates a macro to show the network activity indicator everytime we send and receive data from the flickr web service. Then we synthesize our model.
Also add these:
First, get an api key from flickr. You can get one here:http://www.flickr.com/services/api/
Ok, now let's create our detailViewController. Go to classes folder, right click, select add new file, UIViewController subclass, don't check "with xib for user interface".
In DetailViewController.h, add these:
In DetailViewController.m, add these:
Here we synthesize our model. In loadView, we create a web view that spans the entire screen. We also create method that creates a url string, passing in the parameters of our photo to flickr's server. Then in viewWillAppear we call load our url request that we created in the pictureAddress method.
We will then have the activity indicator activate while we are loading our photo from flickr. We do this by implementing a couple of methods.
ShowNetworkActivityIndicator() and HideNetworkActivityIndicator() are just macros we define as:
Then some house keeping at dealloc:
That takes care of our DetailViewController, now lets create the SearchViewController, the first view of the app.
Right click the classes folder and add a UIViewController with "Xib for user interface".
Then add these in the SearchViewController.h:
Press command b to biuld. Open the SearchViewController.xib, add a UITextField, UIImageView and a UIButton. Arrange them like this:
imageView image
Download the imageView's image from the link above. Drag and drop the image file into your resources folder in xcode. Make sure to check "copy items into destination folder" checkbox. In interface builder, click the image view, press command 1 to bring up the attributes inspector. In image, select "my_flickr_app.png".
Control drag from the file's owner to the text field, and select searchField. Control drag from the button to the file's owner and select searchBtnClicked:. Save and quit.
Here we just synthesize our outlet. We also implement our IBAction. We also implement our search method. We just create an instance of WebServicesViewController pass the contents of out searchField's text to the photoSearch property of our WebServicesViewController (the photoSearch property is just inserted into the SOAP xml string request we created in the first part of this tutorial). We then push the instance of WebServicesViewController to our navigation controller's view.
When you get your own api key, subsitute it to the blackened out part of the code. We then create our SOAP request in the soapMsg string. Then we create our NSMutableURLRequest. We plug in our url. We also plug in our HTTP header values, set our method to POST, and set our body to soapMsg, which we turn into an NSData by sending it the message "dataUsingEncoding:" .
Then we create a NSURLConnection using the NSMutableURLRequest we just created.
When we connect to the web service of flickr, a bunch of NSURLConnection methods will be called, so lets implement them.
The "connection: didReceiveResponse:" method gets called as soon as we receive the response from the service. We create an NSData to receive the data we will get from connection: didReceiveData:. We release our NSData object and our connection if we fail in connection: didFailWithError:.
In connectionDidFinishLoading we get our completed NSData *webData and convert it to NSString to clean up the syntax.
This is how the xml file looks before we clean it up.
This is the "after" picture.
Now lets parse the XML. Lets implement the NSXMLParser methods.
We just parse out the title, server, farm, secret, photo id. These are stored as attributes, so we "get" them from the attributes dictionary that was passed to us, from the method: parser: didStartElement: namespaceURI qualifiedName: attributes:. We don't do anything in parser foundCharacters, because there is nothing between the photo tags, everything is stored as attributes. Then at parser didEndElement we reload our tableView, which we are about to implement next.
Here we just set our numberOfRowsInSection to the number of entries in the photoTitle array. We also set the cell's textLabel and detailTextLabel to the title and the Id respectively. In didSelectRowAtIndexPath we just pass the contents in one of our model (our arrays) to our detailViewController's properties, which we will be creating next.
But before we do that, make sure our model is released in dealloc.
This is how the xml file looks before we clean it up.
This is the "after" picture.
Now lets parse the XML. Lets implement the NSXMLParser methods.
We just parse out the title, server, farm, secret, photo id. These are stored as attributes, so we "get" them from the attributes dictionary that was passed to us, from the method: parser: didStartElement: namespaceURI qualifiedName: attributes:. We don't do anything in parser foundCharacters, because there is nothing between the photo tags, everything is stored as attributes. Then at parser didEndElement we reload our tableView, which we are about to implement next.
Here we just set our numberOfRowsInSection to the number of entries in the photoTitle array. We also set the cell's textLabel and detailTextLabel to the title and the Id respectively. In didSelectRowAtIndexPath we just pass the contents in one of our model (our arrays) to our detailViewController's properties, which we will be creating next.
But before we do that, make sure our model is released in dealloc.
Ok, now let's create our detailViewController. Go to classes folder, right click, select add new file, UIViewController subclass, don't check "with xib for user interface".
In DetailViewController.h, add these:
In DetailViewController.m, add these:
Here we synthesize our model. In loadView, we create a web view that spans the entire screen. We also create method that creates a url string, passing in the parameters of our photo to flickr's server. Then in viewWillAppear we call load our url request that we created in the pictureAddress method.
We will then have the activity indicator activate while we are loading our photo from flickr. We do this by implementing a couple of methods.
ShowNetworkActivityIndicator() and HideNetworkActivityIndicator() are just macros we define as:
Then some house keeping at dealloc:
That takes care of our DetailViewController, now lets create the SearchViewController, the first view of the app.
Right click the classes folder and add a UIViewController with "Xib for user interface".
Then add these in the SearchViewController.h:
Press command b to biuld. Open the SearchViewController.xib, add a UITextField, UIImageView and a UIButton. Arrange them like this:
imageView image
Download the imageView's image from the link above. Drag and drop the image file into your resources folder in xcode. Make sure to check "copy items into destination folder" checkbox. In interface builder, click the image view, press command 1 to bring up the attributes inspector. In image, select "my_flickr_app.png".
Control drag from the file's owner to the text field, and select searchField. Control drag from the button to the file's owner and select searchBtnClicked:. Save and quit.
Here we just synthesize our outlet. We also implement our IBAction. We also implement our search method. We just create an instance of WebServicesViewController pass the contents of out searchField's text to the photoSearch property of our WebServicesViewController (the photoSearch property is just inserted into the SOAP xml string request we created in the first part of this tutorial). We then push the instance of WebServicesViewController to our navigation controller's view.
In viewDidLoad, we just declare our class as the delegate of the searchField. This is done so we can implement the textFieldShouldReturn method, where we want the keyboard to disappear after we press the return button. We also want it to call the startSearch method. Then we clean up our outlet in dealloc.
Ok, now lets go to our WebServicesAppDelegate:
Import all the necessary header files. And in application didFinishLaunchingWithOptions, create an instance of SearchViewController. Make it the root view controller of our navigation controller. Give it a title. Then release the svc (after passing it to the navigation controller we dont need it anymore so we release it). Then make sure to add the nvc's view to our window's subview. So that's it! Build and run and enjoy being able to search for photos in flickr using it's SOAP API. :) For questions, hit the comments.
Hi, I tried the following (part of code):
ReplyDeleteNSString *soapMsg = [NSString stringWithFormat:
@""
""
""
"flickr.photos.search"
"%@"
"soap"
"%@"
"5"
""
""
"",apiKey,@"any"];
And program outputs:
2011-12-29 15:31:06.484 SimpleTable[4817:207] flickr.photos.searchMyKEYsoapany5
2011-12-29 15:31:06.922 SimpleTable[4817:207] Done, received bytes: 408
2011-12-29 15:31:06.923 SimpleTable[4817:207]
flickr.error.0
Invalid SOAP envelope.
http://www.flickr.com/services/soap/
Please see http://www.flickr.com/services/api/ for more details
What is wrong with my SOAP :) (Invalid SOAP envelope)?
And thank You in advance.
I am sorry :), it is impossible to paste the code as an image. I tried to run my application with the same "soapMsg" value (as in your example). But "flickr" returns that my envelope is invalid :(. Could you help me please :)?
ReplyDeleteI solved it. I typed the content of soapMsg as one string/line. (my question is solved). Thank You :)
ReplyDeleteEverything Is Working Perfectly, Thank You!
ReplyDelete