Multipeer Connectivity is a means of identifying and connecting services together, and allows for very easy passing back and forth of data with minimal setup. If you are thinking that this seems similar to Bonjour, you are correct; however, Bonjour is for service discovery, not connection or transmission. Multipeer Connectivity handles everything in one neat package.
Multipeer Connectivity is comprised of a few different components, but it works by having applications advertise their services asking if anyone is available to connect. The service browser listens for these advertisements and can request to create a connection between the devices. If the connection is accepted, a session is created with every one inside the session being represented by a peer object.
To demonstrate how this works, we’ll make a simple chat application using Swift, Apple’s new language.
Note that this exercise is written for iOS 8, but the Multipeer Connectivity framework also works on OS X.
- Create a new Single View iPhone application called
MultipeerChat
. - Open the project in the project navigator and the add the MultipeerConnectivity framework into the project from the Linked Frameworks and Libraries section.
- Open the
Main.storyboard
, and add aUITextView
. Make it take up most of the space, and set its editable field to be false in the Attributes Inspector. - Add a
UITextField
and add two buttons. Label oneBrowse
and the otherSend
. - Connect the
UITextView
up to a property calledchatView
. - Connect the
UITextField
up to a property calledmessageField
. - Connect the browse button up to an action called
showBrowser
, and the Send button up to an action calledsendChat
.
When complete, your interface should look like the following image.
Modify the ViewController
so that is looks like the following:
import UIKit import MultipeerConnectivity class ViewController: UIViewController, MCBrowserViewControllerDelegate, MCSessionDelegate { let serviceType = "LCOC-Chat" var browser : MCBrowserViewController! var assistant : MCAdvertiserAssistant! var session : MCSession! var peerID: MCPeerID! @IBOutlet var chatView: UITextView! @IBOutlet var messageField: UITextField! override func viewDidLoad() { super.viewDidLoad() self.peerID = MCPeerID(displayName: UIDevice.currentDevice().name) self.session = MCSession(peer: peerID) self.session.delegate = self // create the browser viewcontroller with a unique service name self.browser = MCBrowserViewController(serviceType:serviceType, session:self.session) self.browser.delegate = self; self.assistant = MCAdvertiserAssistant(serviceType:serviceType, discoveryInfo:nil, session:self.session) // tell the assistant to start advertising our fabulous chat self.assistant.start() } @IBAction func sendChat(sender: UIButton) { // Bundle up the text in the message field, and send it off to all // connected peers let msg = self.messageField.text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) var error : NSError? self.session.sendData(msg, toPeers: self.session.connectedPeers, withMode: MCSessionSendDataMode.Unreliable, error: &error) if error != nil { print("Error sending data: \(error?.localizedDescription)") } self.updateChat(self.messageField.text, fromPeer: self.peerID) self.messageField.text = "" } func updateChat(text : String, fromPeer peerID: MCPeerID) { // Appends some text to the chat view // If this peer ID is the local device's peer ID, then show the name // as "Me" var name : String switch peerID { case self.peerID: name = "Me" default: name = peerID.displayName } // Add the name to the message and display it let message = "\(name): \(text)\n" self.chatView.text = self.chatView.text + message } @IBAction func showBrowser(sender: UIButton) { // Show the browser view controller self.presentViewController(self.browser, animated: true, completion: nil) } func browserViewControllerDidFinish( browserViewController: MCBrowserViewController!) { // Called when the browser view controller is dismissed (ie the Done // button was tapped) self.dismissViewControllerAnimated(true, completion: nil) } func browserViewControllerWasCancelled( browserViewController: MCBrowserViewController!) { // Called when the browser view controller is cancelled self.dismissViewControllerAnimated(true, completion: nil) } func session(session: MCSession!, didReceiveData data: NSData!, fromPeer peerID: MCPeerID!) { // Called when a peer sends an NSData to us // This needs to run on the main queue dispatch_async(dispatch_get_main_queue()) { var msg = NSString(data: data, encoding: NSUTF8StringEncoding) self.updateChat(msg, fromPeer: peerID) } } // The following methods do nothing, but the MCSessionDelegate protocol // requires that we implement them. func session(session: MCSession!, didStartReceivingResourceWithName resourceName: String!, fromPeer peerID: MCPeerID!, withProgress progress: NSProgress!) { // Called when a peer starts sending a file to us } func session(session: MCSession!, didFinishReceivingResourceWithName resourceName: String!, fromPeer peerID: MCPeerID!, atURL localURL: NSURL!, withError error: NSError!) { // Called when a file has finished transferring from another peer } func session(session: MCSession!, didReceiveStream stream: NSInputStream!, withName streamName: String!, fromPeer peerID: MCPeerID!) { // Called when a peer establishes a stream with us } func session(session: MCSession!, peer peerID: MCPeerID!, didChangeState state: MCSessionState) { // Called when a connected peer changes state (for example, goes offline) } }
This code does the following things:
- It adds a class extension to the
ViewController
class, which makes
it conform to theMCBrowserViewControllerDelegate
and
MCSessionDelegate
protocols, as well as creating four new properties,
including one to handle the Multicast Peer components:- The
MCBrowserViewController
is a prebuilt view controller for handling and negotiating browsing for connections. - The
MCAdvertiserAssistant
is another prebuilt class for both advertising and negotiating creating a connection and session. - The
MCSession
is the object holding the sessions once it has been negotiated. -
MCPeerID
represents your peer id for the session.
- The
- In the
viewDidLoad
method, the code initializes all the Multicast Peer objects before telling the advertiser to start advertising its availability. - In the
sendChat
method, thesendData(toPeers:error:)
message on the session is the real meat of the application. This is the method used to send data—in our application, a string from the text field. - Finally,
session(didReceiveData:fromPeer:)
is the delegate method that is called when the session receives any data—in the case of our application. It appends the new data to the text view, showing the received text to the text view.
Now if you and another friend both (or you, using two devices) run the application, you should have an amazing chat app!
Editor’s note: Dive deeper into Swift with “Swift Development with Cocoa” by Paris Buttfield-Addison, Jonathon Manning, and Tim Nugent.
Public domain handset illustration courtesy of Internet Archive.