This week I’ve been porting a simple J2ME mobile phone application to the iPhone. The J2ME application allows users to login and exchange data with a web application via XML-RPC, so naturally I was keen to use the same server-side scripts for the iPhone app. As far as I know, there is no no specific open source framework available for XML-RPC on the iPhone, but the folks at WordPress for iPhone have rolled their own which is available under the GNU General Public License, and with a little fishing around I was able to get it up and running in my own app. Basic instructions after the jump…
The first step is to download the WordPress for iPhone source code, either via SVN or directly through Trac (Link for v1.21: http://iphone.trac.wordpress.org/changeset/336/tags/1.21?old_path=%2F&format=zip).
When you extract that zip you will see a folder named Classes and inside that a folder named XMLRPC, drag the XMLRPC folder into your project. You will also need to grab NSString+XMLExtensions.h and NSString+XMLExtensions.m and drag them into your project.
That’s all the required files for the XML-RPC framework and now implementing is fairly straight forward. You need to put the following to your header file:
#import "XMLRPCResponse.h" #import "XMLRPCRequest.h" #import "XMLRPCConnection.h"
and to your .m file you need to add something like:
- (NSString *)loginToServer {
NSArray *args = [NSArray arrayWithObjects:@"test",nil]; // the param(s)
NSString *server = @"http://example.com/xmlrpc"; // the server
NSString *method = @"loginUser"; // the method
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithHost:[NSURL URLWithString:server]];
[request setMethod:method withObjects:args];
id response = [self executeXMLRPCRequest:request];
[request release];
if( [response isKindOfClass:[NSError class]] ) {
return nil;
}
else {
return [response valueForKey:@"key"]; // the response key
}
return nil;
}
- (id)executeXMLRPCRequest:(XMLRPCRequest *)req {
XMLRPCResponse *userInfoResponse = [XMLRPCConnection sendSynchronousXMLRPCRequest:req];
return [userInfoResponse object];
}
You need to enter the appropriate values where I’ve commented, but this bare bones example should get you started. You can see more examples by sifting through BlogDataManager.m file in the WordPress for iPhone project.
Leoganda says:
Hi, it’s really good article!
I’m newbie in Iphone development, do you have complete article how to use this xml rpc and linked to the UI??
Thanks
kilbot says:
Hi Leoganda, I don’t have a complete article but I probably help you put together some basic code.. what is the task you are trying to complete?
zero dist0rti0n says:
Cool, do these classes convert the array returned to an NSArray?
kilbot says:
The returned object (*response in the case above) is a NSDictionary, that way you can access the data with key/value pairs.
Leoganda says:
Hi thanks kilbot, I have succeed make simple app with XMLRPC WordPress now :)
Lex says:
Hey Kilbot,
thanks for the info. I need to use XMLRPC for my iPhone app, I tried implementing an example pretty much like what Leo has on his site (http://www.leoganda.net/xml-rpc-on-iphone/). Even if I define response as an id and not NSString, I get a “NSInvalidArgumentException, reason: *** [NSError object]: unrecognized selector sent to instance …” error when I return the response as an object. Have you encountered this as well?
kilbot says:
Hi Lex, the response is returned as a NSDictionary, so depending on how you are trying to access data within that object you could be getting the NSInvalidArgumentException error.
Try logging some notices in the app to see where it is failing, eg:
if( [response isKindOfClass:[NSError class]] ) {
NSLog(@”Something went wrong … there was no readable response”);
return nil;
}
else {
NSLog(@”key: %@”,[response valueForKey:@"key"]);
return [response valueForKey:@"key"]; // the response key
}
return nil;
Where 'key' is some data you expect to get back from the server.
Lex says:
Alrite, I can't figure how the returned data strucutre is composed. I tried looking for an NSDictionary strucutre in the debugger, but no success. My response in XML looks like this:
<methodResponse>
<params>
<param>
<value>
<boolean>0</boolean>
</value>
</param>
</params>
</methodResponse>
I tried using “boolean” and “value” as the key, but that didn't help, I get a “Terminating app due to uncaught expcetion NSUNknownKeyException, reason: NSCFBoolean 0x… valueForUndefineKey: this class is not key value coding-compliant for the key boolean/value/…”
Does the key relate to the XML at all?
Jb says:
Lex – check your comment on the WP iPhone app… The keys are dependent on what the XMLRPC service returns… I.E. you're making a method call for some data and what comes back depends on what you asked for and how that XMLRPC service creates the XML…
ad says:
Hi, I'm trying to develop an application based on your post, and on Leoganda's one, but I'm doing something wrong. My app has an exception everytime.
Terminating app due to uncaught exception 'NSInvalidArgument
Exception', reason: '*** +[NSString decodeXMLCharactersIn:]: unrecognized selector sent to class 0×30692800'
I debugged and found that it crashes on the first line of this function:
- (id)decode
{
[_parser parse];
NSError *parseError = [_parser parserError];
if (parseError) {
return parseError;
}
return decodedValue;
}
Even though, I still don't know what I'm doing wrong. Some advice would be very helpful.
Thanks!
Lex says:
It sounds to me like the argument that is passed to NSString's decodeXMLCharactersIn method is of the wrong type. Make sure that types of your variables support the methods you call on them. This can be tricky due to Objective-C being very dynamic. If you debug and step into the parse method and reach the point where [NSString decodeXMLCharactersIn] is called, you should be able to track down the error.
ad says:
Thanks, Lex.
Now I kinda succeded in establishing a communication between my app and my php WS, but I have some problems with types.
I created the WS using phpxmlrpc library, do you know if it's compatible with the wordpress library? I sometimes find that I dont get returned a NSDictionary but a String.
I also would like to know how to send integers or other types to the WS, not only strings.
Thanks!
Guest says:
Hi thanks for this example. I'm using SDK 3.1.2 and things compiles fine but when I use it I have a strange problem. I get errors when the rpc function returns a simple string, also if I return a Map the maps has all empty entries?
Could this be due to the code being old ? Also what are most people using to communicate with server side from the iPhone ? XML-RPC seems to be not as heavily used.
thanks
kilbot says:
I haven't developed anything for the iphone since I wrote this article, but the feeling I got at the time was that XML-RPC was the exception rather than the rule for web services.
I believe that most developers are using simple HTTP calls like POST, GET, PUT or DELETE and then parsing the output, depending on your app this might be XML or JSON or something similar.
As I say, I haven't played with this stuff for a while, but a quick search on Google turned up some stuff that might be worth looking at:
http://allseeing-i.com/ASIHTTPRequest/ (a HTTP wrapper in objective-c)
http://www.mobileorchard.com/tutorial-json-over... (a tutorial for parsing JSON)
And you should always look at the info and tutorials at developer.apple.com to see if any native functionality will fit your needs: http://developer.apple.com/iphone/library/navig...
Tim says:
Thanks so much for this info. I have been trying to do exactly this for the past week. I am having trouble with some odd parts of it, but I was able to work around it.