DEV Community

Nasir Ahmed Momin
Nasir Ahmed Momin

Posted on • Edited on

iOS Chat App with XMPP framework

Wants to build Chat App for iOS?

Lets gets started
XMPP stands for Xtensible Messaging & Presence Protocol.

Things required ?

  1. IM Server (I prefer MongooseIM)
  2. User (Account created)

You can download MongooseIM Package here & Install package
https://www.erlang-solutions.com/resources/download.html

Details for installation can be found here https://mongooseim.readthedocs.io/en/latest/user-guide/Getting-started/

On installation completes launch Terminal & execute following command
$ mongooseimctl start

then Check status
$ mongooseimctl status

When All thats done. You need a user, head down below & create user

$ mongooseimctl register <user> <host> <password>

Eg: $ mongooseimctl register user1 localhost qwerty

You can verify user creation $ mongooseimctl registered_users localhost

Till now server config & user creation completed.

Before jumping into code part, lets understand following things

  1. JID
  2. Stanza & its type.
  3. Stream.

    1. JID: is something by which each individual is uniquely identified is XMPP. It does looks like this username@hostname/resource username: is local part hostname: is domain part resource: is resource part which is optional in many cases
    2. Stanza: is name of XML tag/piece that sends & received. Basic Stanza's are < message > < presence > & < iq >, details will be mentioned about them, if required in future
    3. Stream: is entry point for interprocess communication to start on shared file called Socket, which happens by < stream > tag.

We shall start working on iOS App.
I hope you guys knows how to create Xcode iOS Project & Pod setup.

In Podfile pod 'XMPPFramework'
then run pod install

Create XMPPController.swift file & make a singleton object.

class XMPPController: NSObject {
    static let sharedInstance = XMPPController()
}

Now declare an XMPPStream instance & intilize it in init()

var stream: XMPPStream?
override init() {
  self.stream = XMPPStream()
  super.init()
}

Also declare following vars.

var hostName: String?
var userJID: XMPPJID?
var hostPort: UInt16?
var password: String?

Declare a connect function as below

func connect(withHostName name: String, userJID jid: String, hostPort port: UInt16, password pwd: String) {

    guard let uJID = XMPPJID(string: jid) else {
        return
    } 

    hostName    = name
    userJID     = uJID
    hostPort    = port
    password    = pwd

    // Stream Configuration
    stream?.hostName = name
    stream?.myJID = uJID
    stream?.hostPort = port
    stream?.startTLSPolicy = .allowed

    if stream!.isDisconnected {
        do {
            try stream?.connect(withTimeout: 10)
        }
        catch let e {
            print(e.localizedDescription)
        }
    }
}

Once we reached till here, we have forgot most important thing.
without confirming delegate of stream our XMPPController wont able to receive any callbacks, add following lines in init

self.stream?.addDelegate(self, delegateQueue: DispatchQueue.main)

XMPPStreamDelegate as set of delegate functions among them we will use only couple of, add following code as below

extension XMPPController: XMPPStreamDelegate {
    func xmppStreamDidConnect(_ sender: XMPPStream) {
       print("Stream Connected")
       try! stream?.authenticate(withPassword: password!)
    }

    func xmppStreamDidAuthenticate(_ sender: XMPPStream) {
       print("Stream: Authnticated")
       stream?.send(XMPPPresence())
    }
}

Once xmppStreamDidConnect(:XMPPStream) is connected, we are making sure that authentication should initiate & on authentication xmppStreamDidAuthenticate(:XMPPStream) will receive callback

Entire code is available on github repo
https://github.com/momin96/Mobile-Chat-App

Top comments (0)