Consuming RESTful API with RESTframework

As explained in previous post, we’re going to demonstrate how RESTframework handles REST web services. I’ll be consuming a simple Django demo web service created in previous post, so either grab the sources or read the post and build it yourself. Assuming you have this service running on localhost, port 8000, we can continue.

First, download RESTframework from GitHub. With git client, simply type in terminal:

$ git clone git@github.com:ivasic/RESTframework.git

The quickest way to get RESTframework into your project is just including all the files from RFClasses  folder. RF does not have any external dependencies so building shouldn’t be a problem.

RFClasses

RFClasses

Now, we’ll also need JSONKit to parse API response and MBProgressHUD to show some progress. Grab both from GitHub and add to your project.

Fetching objects list

We’ll have 2 view controllers in our demo app. One will be a simple object list and the other one will be, even more simple, view controller for creating a new object. First, we’re going to show how to fetch the object list. We’ll need a GET request to /objects/ URL and we’ll need to parse the JSON array we get in response and show in the table view.

RFRequest* r = [RFRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/"] type:RFRequestMethodGet resourcePathComponents:@"objects", nil];
[MBProgressHUD showHUDAddedTo:self.view animated:YES].labelText = NSLocalizedString(@"Loading...", @"");
[RFService execRequest:r completion:^(RFResponse* response) {
	[MBProgressHUD hideHUDForView:self.view animated:YES];
 
	if (response.error) {
		UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") message:response.error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
		[aiv show];
		return;
	}
 
	self.dataSource = [response.dataValue objectFromJSONData];
	[self.tableView reloadData];
}];

So, what we’re doing in this code snippet is:

  • Creating a GET RFRequest with appropriate URL and resource path
  • Attaching MBProgressHUD to our view to show spinner progress
  • Executing RFRequest and defining the block to execute after RFResponse is received
  • Inside this block, we simply check for errors, parse the response, add to our tableView dataSource and reloading the table
You can see all this in action in the project sample attached to this blog post (at the bottom).

Creating new objects

Our view controller for creating new objects is responsible for creating POST requests to /objects/ URL. Again, very simple, you just need to do this:

RFRequest* r = [RFRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/"] type:RFRequestMethodPost resourcePathComponents:@"objects", @"", nil];
 
[r addParam:self.txtName.text forKey:@"name"];
[r addParam:self.lblDate.text forKey:@"date"];
 
[MBProgressHUD showHUDAddedTo:self.view animated:YES].labelText = NSLocalizedString(@"Submitting...", @"");
[RFService execRequest:r completion:^(RFResponse* response) {
	[MBProgressHUD hideHUDForView:self.view animated:YES];
 
	if (response.error) {
		UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") message:response.error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
		[aiv show];
		return;
	}
 
	UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:@"Success" message:@"Success" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
	[aiv show];
 
	[self.navigationController popViewControllerAnimated:YES];
}];

Similar to our previous snippet, but this time we also add some parameters to the request – name and date strings.

This is a brief overview with sample Xcode project of how RESTframework consumes RESTful web APIs. Questions welcomed via comments as usual.

 

Download project: RESTframework demo Xcode project download

REST framework for iOS is now Open Source

I have (finally) open sourced my RESTframework project on GitHub. It aims for simplicity of usage primarily. Querying RESTful web services is really easy now. Supported are iOS versions 4.0 and above and Mac OS 10.6 and above.

Feel free to fork & contribute!

RESTframework on GitHub

Some XCode 4 tips

Apple kind of surprised me with releasing the XCode 4 along with the iOS 4.3. Honestly, I wasn’t expecting it until later this year or at least until iOS 5 was announced. But I’m glad it’s out, of course, and I already switched to using it vs XCode 3. I held back from trying out the beta versions so the experience was really exciting to me when I first tried it. Completely different experience compared to version 3.x and finally a single, fullscreen window. Pretty cool.

Anyway, I’m not going to review it as there are lots of reviews, I’m just going to point out a few things that I ran into while testing the last few days.

How to enable LLVM in XCode 4

By default, XCode uses a GCC kind of wrapper for LLVM so you’ll probably want to enable LLVM compiler and you can do that easily enough in build settings like so.

Now that you enabled that naturally you want to enable LLDB too. LLDB is a debugger, it’s to LLVM what GDB is to GCC. To enable LLDB you need to choose “Edit Scheme” from the “Product” menu and for the “Run” phase you’ll see a debugger chooser dropdown. However, at this point for iOS projects you’re stuck with GDB as the LLDB is only available for Mac apps and not available for iOS, yet.

How do I add existing frameworks to the XCode 4 projects?

“Add the existing framework…” right click menu option is gone. So how do you add existing frameworks?! The option is there of course, it’s just a bit hidden. The trick is to open target settings and navigate to the “Build Phases” tab. There’s a section that says “Link binary with Libraries” and that’s our X. See below.

Add existing frameworks

Add existing frameworks

So, should I switch to XCode 4?

Yup. I was in doubt and thought it might be a good idea to hold off of it for a while, at least until the next version but I tried it and found nothing that stops me from using it. In fact, I’m so pleased I’m having a hard time coding some legacy projects in XCode 3. I would suggest, though, to keep the version 3.x and install XCode 4 in a separate directory just in case…

UPDATE:

Where do I set NSZombieEnabled?

Got another tip here, it’s moved to a different place now. You need to choose “Edit Scheme” from the “Product” menu and you’ll find it there.

Edit Scheme Xcode 4

Edit Scheme Xcode 4

Calling JSON-RPC webservice in iOS

This topic is already covered in my post for consuming .NET web services in iOS but some questions were raised about passing arguments to the JSON-RPC methods that require them. In this short post I’ll just explain how to do just that.

Assume you have a few RPC methods that require some arguments like this.

[Jayrock.JsonRpc.JsonRpcMethod("HelloWorld")]
public string HelloWorld()
{
	return "Hello World!";
}
 
[Jayrock.JsonRpc.JsonRpcMethod("Echo")]
[Jayrock.JsonRpc.JsonRpcHelp("Simple echo method, takes string input and returns it")]
public string Echo(string input)
{
	return input;
}
 
[Jayrock.JsonRpc.JsonRpcMethod("EchoArray")]
[Jayrock.JsonRpc.JsonRpcHelp("Returns input arguments as an array of strings")]
public List EchoArray(string str1, string str2, string str3, string str4)
{
	List lst = new List();
	lst.Add(str1);
	lst.Add(str2);
	lst.Add(str3);
	lst.Add(str4);
 
	return lst;
}

Now, those “Echo” methods need some arguments passed to them and in this case I worked with strings but remember those args can be any primitive or complex but serializable types. So now that we have a working web service, we can query it from iOS. I’ll refer to my old example project which can be found here. The way it’s coded right now is to call the HelloWorld method without any arguments like this.

JSONRPCService* svc = [[JSONRPCService alloc] 
	initWithURL:[NSURL URLWithString:txtURL.text]];
svc.delegate = self;
 
[svc execMethod:@"HelloWorld" andParams:[NSArray array] withID:@"1"];

We need to notice that we passed an empty NSArray for params. This is because our HelloWorld doesn’t need any arguments. Easily enough, if you want to call the Echo method with a single param you’ll just add a string to an array and pass that array as execMethod:andParams:withID  2nd argument.

JSONRPCService* svc = [[JSONRPCService alloc] 
	initWithURL:[NSURL URLWithString:txtURL.text]];
svc.delegate = self;
 
[svc execMethod:@"Echo" andParams:[NSArray arrayWithObject:@"Echo Me!"] 
	withID:@"2"];

You can pass as many arguments as your method requires just stack ‘em up in an NSArray and make sure the argument order complies with the argument order of the web method.

JSONRPCService* svc = [[JSONRPCService alloc] 
	initWithURL:[NSURL URLWithString:txtURL.text]];
svc.delegate = self;
 
[svc execMethod:@"EchoArray" 
	andParams:[NSArray arrayWithObjects:@"1st arg", @"second arg", @"3rd arg", @"4th arg string", nil] 
	withID:@"3"];

Hope this helps!

JSON (de)serialization in iOS

A few people asked how to serialize and deserialize JSON data in iOS projects. I know it’s covered on almost every cocoa blog on this planet and basically very simple, but I’ll describe in this short post anyway. There are a couple JSON libraries for Objective-C that I know of, but the 2 most popular and widely used are TouchJSON and SBJSON. Both are very simple to use although TouchJSON developers seem to be a bit more active.

TouchJSON

You start by downloading TouchJSON files from GitHub and including them into your project.The next step would be importing header files CJSONDeserializer.h and/or #import “CJSONSerializer.h” and you’re good to code it. Very simple, like this:

Deserialization:

CJSONDeserializer *jsonDeserializer = [CJSONDeserializer deserializer];
NSError *error;
NSDictionary *resultsDictionary =
          [jsonDeserializer deserializeAsDictionary:jsonData error:&error];

Where jsonData is a string representation of your json data.

Serialization:

    NSString *jsonString = [[CJSONSerializer serializer]
               serializeObject:myDict];
    NSData *data = [jsonString dataUsingEncoding: NSUTF8StringEncoding];

where myDict is a NSDictionary you want to serialize. You can also use jsonString directly if you don’t need NSData…

SBJSON

Similar stuff here too, download the files and include them in your project. After that, a simple import of “JSON.h” in your implementation files enables you to parse JSON with ease.

Serialization

NSString* jsonString = [myDict JSONRepresentation];

That’s it. myDict is a NSDictionary* and with a single line you converted it to its JSON representation.
Deserialization

NSDictionary* result = [jsonString JSONValue];

Again, a single line and you converted your jsonString NSString object to Cocoa NSDictionary structure.

Which one should I choose?

Both are simple and fast, although I didn’t benchmark them. I’d suggest to try out both and make your pick, you certainly won’t go wrong with either. I personally go with SBJSON just for the sake of ultra simplicity.

 

BTW,  if you run into problems with linking JSON libraries (e.g. you’re already using some library that includes JSON library) make sure you read about this, you will find it helpful.

Worldy Wings: retro air fighter iPhone game

Yesterday I stumbled upon a really nice game called Worldy Winds. It’s a shoot-em-up air fighting game similar to 1942 and 1951 but the gameplay seems better to me. Also, integrated Game Center adds more fun to the game. You have 3 different planes to choose from 5 worlds which is not so good cause you can go through them relatively quickly. But the good side is that you can play all over again to beat your previous score and brag to your friends about it on the Game Center. It integrates GC leaderboards and achievements (a lot of them) so it’s pretty fun to match your score against other players.

All in all, a really nice shooters game if you’re up to it. The only downside is that the graphics, even though beautiful, don’t look so good on iPhone 4 cause the game doesn’t support retina display. I hope the devs include this in the next update or so and make this app even more gorgeous. Also, a bit more levels wouldn’t hurt ;)

The app is available on AppStore for $1.99 at the time of writing.

Simple UIView transitions animation using blocks in iOS 4

UIView’s sweet animation capabilities we were used to in pre-iOS 4 are now deprecated and Apple suggests we start using blocks which is far more convenient and simpler way of achieving the same thing. I’ll demonstrate how to make a simple UIView transition using new blocks based API vs using the old non-blocks way.

Our Goal

is to make an UIView curl up & down when adding and removing to a superview like shown below.

UIView page transition

UIView page transition

The Old Way – using +beginAnimations:context:

The old way code, using UIView’s class methods +beginAnimations:context: was simple enough and the code looks like below.

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown 
                                      forView:containerView cache:YES];
 
[containerView addSubview:subview];
 
[UIView commitAnimations];

Using blocks based API

Recommended usage of blocks API would change this code snippet to something like this.

[UIView transitionWithView:containerView duration:0.5
		options:UIViewAnimationOptionTransitionCurlDown
		animations:^ { [containerView addSubview:subview]; }
		completion:nil];

Now, this is all quite simple, nice & cute yet problems are likely to arise and you end up without animations. I’ve run into this myself, the problem is that one can easily make a mistake of passing options argument of the wrong type. The old way required UIViewAnimationTransition for transition argument while the blocks based API requires UIViewAnimationOptions for options argument. These are, obviously, completely different types but because they are both enum’s (int’s) you won’t get a compiler warning from XCode and if you mix them up you can spent quite some time trying to figure out why your animation doesn’t appear. Moreover, XCode’s autocomplete doesn’t even offer UIViewAnimationOptions when auto-completing. It tricked me and I was bumping my head why a perfectly good piece of code wouldn’t work.

All in all, make sure you don’t mix UIViewAnimationOptions with UIViewAnimationTransition when using transitionWithView:duration:options:animations:completion: method! I hope you enjoyed this mini tutorial for beginners, the XCode demonstration project is below.

UIView transitions animation XCode demo project.

How To: Send photos from your iPhone/iPad to your computer over WiFi

Sending and sharing photos from your iPhone, iPod Touch or iPad is supposed to be easy with iTunes syncing but sometimes you can’t (or don’t want to) plug in your iOS device to the computer just to send over a couple of images. There’s a nice and simple tool that allows you to shoot over photos from your phone/pad to your computer or your friends using wireless connection.

AS Share Photo – send photos via WiFi to iPhone, iPod Touch, iPad and desktop Computers

AS Share Photo is a simple iOS app that helps you sharing your photos to your friends or transferring images to your own computer(s). The process is simple and fast unlike some other similar apps I’ve tried. For example, I saw a lot of recommendations for Eye-Fi app which, as much as it is supposed to be good, required a website registration and this extra step made me remove it from my phone instantly. AS Share Photo doesn’t require any website integration and works on your device right away.

In order to share your photos, just open the app and you’ll be presented with the simple interface. You can choose existing photos from your library or you can take new photos using camera.

AS Photo Share

AS Photo Share main window

Once you select the photos you want to share, you will be presented with a screen which explains how to get them on another iOS device or a computer. You can send the photos to the other iOS devices running this app by entering their IP address (IP address of the other device is printed on the main screen, see above) or you can access the interface for downloading photos by using your computer browser and browsing to the URL which the app prints you in the blue box (the design is not so great, but you’ll see it).

AS Photo Share

AS Photo Share sharing window

Now if you’re using your computer browser, just type http://192.168.1.4:65531/ (your URL will probably be different) and you’ll be able to download the photos you specified in previous step.

AS Photo Share web interface

AS Photo Share web interface

As simple as that! Quick too.

The Good

The app is simple enough and provides just what you need – sharing photos quickly without plugging in your device.

The Bad

Not so much from this 2-screen simple app, but the design is not so fancy and also I had troubles with trying to share multiple (10+) photos – the interface was lagging a bit. Also, the whole process of selecting multiple photos is not much user friendly so this is something that devs could improve in some future releases.

The app can be downloaded from Apple’s AppStore.

Duplicate symbols when linking ObjectiveC static libraries

When you link a static library that’s using ObjectiveC categories, you usually have instructions from the developers to add -ObjC and -all_load linker flags which solve linking problems and prevent crashes. Now, if you happen to have the same categories or other objc symbols in your project that uses this static library you’ll get linker errors for duplicate symbols. The most common example for this is using touch JSON framework. I have this static library that uses it, and I also use it in my own code. I’m running into this linking problem every once in a while so I’m going to explain it here and provide a solution for fixing/avoiding it.

The Problem

Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1

ld: duplicate symbol _OBJC_METACLASS_$_SBJSON in /Users/ivan/Projects/MyApp/sources/Trunk/MyApp/libtest-simulator.a(SBJSON.o) and /Users/ivan/Projects/MyApp/sources/Trunk/MyApp/build/MyApp.build/Debug-iphonesimulator/MyApp.build/Objects-normal/i386/SBJSON.o

WARNING: I’ll be talking about problems with touch JSON library because this is the common problem. Solutions may not apply to other libraries although the principle is more-less the same. Be warned.

Scenario #1

“My project uses 1 static library and both this library and my project need JSON framework”.

Simplest solution that might work is to remove -ObjC and -all_load linker flags. When I say ‘might’, I mean that you need to be extra careful with this. If you do this, the static library you link will depend on JSON code from your project so if there’s, for example, a version mismatch you’ll run into serious problems.

LInker Flags in Xcode

Linker Flags

Scenario #2

“My project uses a static library which depends on JSON framework but this library also links other ObjectiveC static libraries. Both my project and this static library need JSON framework”

OR

“I cannot remove -ObjC and -all_load because I need to properly link categories inside a static library, but I also need to add JSON framework to my own project”

Now this is a specific scenario I ran into earlier. I wanted to use Three20 library which links several different ObjC libraries of its own so I definitely need -ObjC and -all_load flags otherwise my app crashes. On the other hand, I had another static library which uses JSON framework and adding this framework to my project causes duplicate symbols linker error.

The solution is simple again but you also need to be extremely careful. You leave those linker flags to properly link ObjC libraries but you don’t add JSON framework in your project. Instead you depend on JSON library linked with the static library you are using. You will, however, need to add header files in order to avoid compilation errors in your own code. Possible problem here is header files vs. compiled code in the static library mismatch. So you need to make sure that the JSON header files you’re using match the JSON code version linked with the static library. If you already imported JSON framework, just remove .m files in XCode from your target.

JSON framework xcode

JSON framework files

Bottomline

Obviously, these are some rare cases of linking problems however, JSON touch framework is a very popular framework and it’s not uncommon that some 3rd party libraries you want to use are built on top of it. My final advice is to understand the problem and why it happens, then you will be able to solve it one way or the other. Good luck!

Unreal Engine 3 on iOS devices

Today I got to try Epic Games ‘Epic Citadel’ free app from Apple’s AppStore which demonstrates the capabilities of Unreal Engine 3 and I must say I’m impressed. This is by far the best 3D environment I’ve seen for mobile devices and also a good sign that the games on iOS devices have a bright future. I took several screenshots posted below so you can enjoy the colors.

The engine features [via Epic Games]:

  • Amazing visuals. “Epic Citadel” pushes the envelope for stunning visuals on iOS devices. Through the latest advances in Unreal Engine 3 technology, the application delivers unrivaled graphics and special effects that immerse players in the kingdom’s grounds.
  • Bump offset mapping. Also known as parallax mapping or relief mapping, bump offset mapping enhances the visual appearance of stone walls and rocks providing intricate textures.
  • Normal mapped architecture. Brings stunning detail to bricks and ground surfaces within the environment.
  • Texture blending with painted weight maps. Refines nuances on roads and terrain, making them rich and lifelike.
  • Global illumination. Unreal Engine 3’s built-in global illumination system, Unreal Lightmass, provides realistic lighting and shadows with minimal development resources.
  • Dynamic specular lighting with texture masks. Helps create authentic cobblestone roads and vivid reflective marble surfaces, while lens flares and light coronas add dramatic emphasis when panning across light sources.
  • Real-time reflections and animation. Environment mapping enables real-time reflections on objects such as the statue inside the cathedral. Dynamic movements of trees and banners are made possible through the use of vertex deformation and skeletal animation.
  • Free tools. Epic’s Unreal Development Kit (UDK), available for free download at http://www.udk.com/download, ships with the same tools and technologies used to create Epic Citadel.