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.

Guess who’s back?

I know it’s been a while. Quite a while actually. Wish my absence was due to the unexpected 5 months vacation at the Caribbean but of course, it’s less popular than that. I got stuck with a bunch of projects – as simple as that. Naturally I wanted to give up on my blogging career but I got some really interesting emails from you guys and also I noticed an increase in visits instead of the other way around. So I’m gonna give this blog another shot, hopefully we can last longer this time.

Stay tuned, I’m going to address most of your comments & questions in the upcoming post(s).

September roundup

It’s been a month already so let’s see what we had so far on Dizzey.com.

For Cocoa & XCode junkies there’s a nice small collection of macros ready to be used in your project. Also, we discussed what to do and how to solve duplicate symbols linking problems and there’s also a small beginners tutorial that explains how to do UIView transitions the blocks based iOS 4 way.

On Mac dev subject we covered in 2 parts how to package Java apps into Mac OS app bundle and how to create a pkg installer for Mac OS app bundles.

We touched Windows Phone 7 development as well, talking about geocoding and creating our very first Phone 7 app.

There’s also several more posts listed below.

How to make pkg installer for Mac apps

In the previous post, I explained how to make a Mac app bundle for Java apps and in this post I’ll explain how to package apps and create Mac pkg installer for your applications. This obviously applies to non-Java apps as well hence the generalized title.

The only tool we’ll need for this is ‘Package Maker’ app that comes with Mac development tools bundle.

Package Maker

Package Maker

If you’re in a hurry and don’t care much about the details, you just drag & drop the files you want installed (your .app, images, docs etc…) into the left sidebar and fill in the basic fields (app title, installer description) and you’re good to go. However, this little app holds much more advanced options and if you care to dig in a little bit you’ll find much more options for customizing your app setup process. Below are the few examples but there is, of course, a lot more.

Although this post doesn’t look like a step-by-step how-to, if you just need a way to package your app without much trouble you just point ‘n’ shoot and you’re done. I might explain the advanced options some time in the future though.

How to create Mac OS app bundle for Java apps

Java apps work great on our Macs, JAR bundles are recognized “out of the box” and launched as executable files automatically by the operating system. But we always want more and we want to be as native as possible so naturally we would like to package our JAR’s into .app bundles to give them more Mac look & feel. In this post I’ll explain how to easily create Mac app bundles out of your Java app JAR’s using Mac OS development tools.

Preps

We’ll need a few things to begin with and those are the JAR file(s) you’re bundling and the app icons. Icons need to be in Mac OS .icns format and there’s a nice tool that will create this for you and it’s called “Icon Composer”. Icon composer (as well as other tools I’ll mention in this post) is installed along with Mac OS development tools from Apple’s website.

Using Icon Composer to create .icns is pretty straight-forward process. You will just need a 512×512 PNG of your icon and you just drag & drop it into the Icon Composer and save as .icns.

Icon Composer

Icon Composer

Bundling Mac OS app

The thing to do is to actually create a Mac OS .app bundle from you JAR file(s) using “JAR bundler” tool (comes along with Mac OS development tools). The app interface is simple enough – you get to choose your JAR executable and specify main class and you’re good to go. There’s, of course, more options if you want to include additional jar’s or files and to specify basic properties for your Java app.

JAR bundler

JAR bundler

Now if you have a single JAR file you shouldn’t have any problems. However, if your JAR file depends on some external libraries, images etc. you might have troubles with dependency file paths. I did. I had a subfolders “lib” and “images” full of external libraries and images my app was using. I tried to solve it ‘their’ way by trying to fix the paths but it took a long time and I couldn’t get it working so I found a much quicker workaround I want to share here.

Instead of having multiple JAR files and additional dependencies, I decided to end the nightmare of handling file paths by bundling everything into one single JAR file. And directly from NetBeans too. There’s a well documented tutorial here. Basically, you need to put the code below in your build.xml file and choose target package-for-store when building your app and a single JAR will be created for you.

<target name="package-for-store" depends="jar">
 
        <!-- Change the value of this property to be the name of your JAR,
             minus the .jar extension. It should not have spaces.
             <property name="store.jar.name" value="MyJarName"/>
        -->
        <property name="store.jar.name" value="MyJarName"/>
 
        <!-- don't edit below this line -->
 
        <property name="store.dir" value="store"/>
        <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>
 
        <echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>
 
        <delete dir="${store.dir}"/>
        <mkdir dir="${store.dir}"/>
 
        <jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
            <zipgroupfileset dir="dist" includes="*.jar"/>
            <zipgroupfileset dir="dist/lib" includes="*.jar"/>
 
            <manifest>
                <attribute name="Main-Class" value="${main.class}"/>
            </manifest>
        </jar>
 
        <zip destfile="${store.jar}">
            <zipfileset src="${store.dir}/temp_final.jar"
            excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
        </zip>
 
        <delete file="${store.dir}/temp_final.jar"/>
 
    </target>

Now all you need to do is to use this JAR file with JAR bundler and you’ll have a Mac OS .app in no time ready to send to your users.

In the next post, I’ll write how to use this Mac OS .app to create an installer for your app. Until then, stay tuned!

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!