陈斌彬的技术博客

Stay foolish,stay hungry

XMPP -How to Work With IQ, Message, & Presence Elements

Where is the API?

The 3 primary XMPP elements (IQ, Message, & Presence) all extend the XMPPElement class. If you take a look at the XMPPElement class, you’ll see that it extends NSXMLElement.

Apple’s documentation for NSXMLElement

NSXMLElement extends NSXMLNode.
Apple’s documentation for NSXMLNode

With these powerful XML libraries, you should have everything you need to quickly extract information from any XML element.

But why isn’t there a method to do X, which I believe should exist in any chat framework?

Because XMPPFramework is not a chat framework. (Although it can certainly be used as such.) XMPP stands for “eXtensible Messaging and Presence Protocol”. XMPP can be used for a ton of different things. In fact, there are a ton of companies that are using XMPP for functionality unrelated to chat. One example is a company that is using XMPP in health care to deliver patient monitoring alarms to devices that nurses carry around.

Now, there are literally hundreds of extensions to XMPP. (Official List) In addition to this, XMPP was designed to be extensible enough to allow you to extend the protocol in any way you want for your application. If the XMPP framework shielded the developer from all the “nasty details” of the XML, the framework itself would be less extensible for you. The fact of the matter is that XMPP is XML. Let’s look at a concrete example:

You write an application called “political debate”, and your users want to be able to express their mood with each chat message they send. The mood will be reflected in other people’s chat window by the background color of the chat bubble. This way, when the debate participants start to get heated up, their chat bubbles start to get red. It’s the biggest feature request for version 2.0. So how do you implement it?

Very easily! You recall that with XMPP, you can add any custom elements you want to a message. So you add something like this:

<message to="group_chat@political_debate.com/obama_healthcare">
    <body>I disagree with you sir!</body>
    <mood>hot</mood>
</message>

Now on the receiving side, you’ll need to access the XML in order to check for <mood/> elements.

How do you get the body of the message?

NSString *body = [[message elementForName:@"body"] stringValue];

How do you get the mood of the message?

NSString *mood = [[message elementForName:@"mood"] stringValue];

But I want all of the XML logic separated from my GUI code!

Great idea. Which is why we’ve separated the various XML types into separate classes (XMPPIQ, XMPPMessage, XMPPPresence). All you have to do is add your own custom categories to those classes. (Categories are an objective-c feature that allow you to add methods to an existing class).

Here’s an example of how you might add a “mood” method to the XMPPMessage class:

@interface XMPPMessage (PoliticalDebate)

- (NSString *)mood;

@end

@implementation XMPPMessage (PoliticalDebate)

- (NSString *)mood
{
    return [[self elementForName:@"mood"] stringValue];
}

@end

So with categories, you can add any methods you want to the element subclasses, and keep your XML logic separate from your GUI logic.

Side Note:

The XMPP Framework was developed before the iPhone SDK was even released. When Apple released the iPhone SDK they decided not to include NSXMLElement and NSXMLNode. This means the iPhone didn’t include any simple objective-c libraries for working with XML DOM. KissXML was created as a drop-in replacement. So you can still refer to the NSXML documentation, and the API should be exactly the same, and the methods should work exactly the same.