Show Menu

Looking to hire an app developer?

Submit your 30 day Job Listing for FREE

This tutorial will help you to establish a connection between two iOS devices via Bluetooth using the GameKit framework. First you need to import the GameKit framework to your project. In XCode 4 you need to go to you target “Build Phases” tab and add GameKit.framework to the “Link with Binary Libraries” list.

Then you need to set up a GKSessionDelegate. You need to carefully decide which of your classes is going to be the delegate because if you pick the wrong one you end up having to rewrite large parts of your code. The basic question is – when do you need to send and receive data? If it is just a one-off occasion you can set a certain view controller as the delegate but if you need the iPhones to stay connected all the time when the user navigates between multiple views it’s probably the best idea to set your ApplicationDelegate as GKSessionDelegate and GKPeerPickerControllerDelegate.

A good tip if your’re doing this is to make a macro that allows you to access the ApplicationDelegate from anywhere in your code. Don’t forget you have to #import the header file anywhere you need to use this. With this you can access any property of the delegate just by UIAppDelegate.anyProperty and you don’t have to write the lengthy piece of code every time.

#define UIAppDelegate ((HelloWorldAppDelegate *)[UIApplication sharedApplication].delegate)

Important thing, the class you will use needs to conform to two protocols as shown below – GKSessionDelegate for handling the session and GKPeerPickerControllerDelegate for estabilishing the connection. Also it is a good idea to set up three properties as show below.

@interface HelloWorldAppDelegate : NSObject <UIApplicationDelegate, GKSessionDelegate, GKPeerPickerControllerDelegate> {
    GKPeerPickerController *connectionPicker;
    GKSession* connectionSession;
    NSMutableArray *connectionPeers;
}
@property (retain) GKSession* connectionSession;
@property (nonatomic, retain) NSMutableArray *connectionPeers;
@property (nonatomic, retain) GKPeerPickerController* connectionPicker;

Then you need to properly initialize all those so add this somewhere to your code (didFinishLaunching or viewDidLoad).

connectionPicker = [[GKPeerPickerController alloc] init];
connectionPicker.delegate = self;
//NOTE - GKPeerPickerConnectionTypeNearby is for Bluetooth connection, you can do the same thing over Wi-Fi with different type of connection
connectionPicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
connectionPeers = [[NSMutableArray alloc] init];

Now you need to add methods that are needed to conform to the GKPeerPickerControllerDelegate. There is nothing much to do there, you can just copy them and change the session ID to the ID your app will use.

#pragma mark - GKPeerPickerControllerDelegate
- (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type {
    // Create a session with a unique session ID - displayName:nil = Takes the iPhone Name
    GKSession* session = [[GKSession alloc] initWithSessionID:@"com.myapp.connect" displayName:nil sessionMode:GKSessionModePeer];
    return [session autorelease];
}

// Tells us that the peer was connected
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session {
    // Get the session and assign it locally
    self.connectionSession = session;
    session.delegate = self;

    [picker dismiss];
}

And now comes the most important part – GKSessionDelegate. The principle for sending data is to convert them into NSData. If you are really sure you will need to send just, say, one NSString than you can encode it directly and just send it. But if you need to send anything more complicated I strongly recommend using the technique with an array and NSKeyedArchiver because it leaves plenty of space for later changes and allows you to send different chunks of data. As you will see this is even probably the easiest method for distinguishing what you actually received – you always get encoded array and when you recreate the array you can test which elements are in it. Note that you could also use NSDictionary. And don’t forget that if you send some custom classes they need to conform to the NSCoding protocol!

//Method for sending data that can be used anywhere in your app
- (void)sendData:(NSArray*)data {
    NSData* encodedArray = [NSKeyedArchiver archivedDataWithRootObject:data];
    [UIAppDelegate.connectionSession sendDataToAllPeers:encodedArray withDataMode:GKSendDataReliable error:nil];
    [encodedArray release];
}

And now the method for receiving data.

#pragma mark - GKSessionDelegate

// Function to receive data when sent from peer
- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context {
    NSArray *receivedData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    //Handle the data received in the array
    [receivedData release];
}
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
    if (state == GKPeerStateConnected) {
        // Add the peer to the Array
        [connectionPeers addObject:peerID];

        // Used to acknowledge that we will be sending data
        [session setDataReceiveHandler:self withContext:nil];

        //In case you need to do something else when a peer connects, do it here
    }
    else if (state == GKPeerStateDisconnected) {
        [self.connectionPeers removeObject:peerID];
        //Any processing when a peer disconnects
    }
}

And finally two methods to call when you want to connect or disconnect, usable from anywhere in your app.

- (void)connectToPeers:(id)sender {
    [UIAppDelegate.connectionPicker show];
}

- (void)disconnect:(id)sender {
    [UIAppDelegate.connectionSession disconnectFromAllPeers];
    [UIAppDelegate.connectionPeers removeAllObjects];
}

With this tutorial you should be able to set up basic Bluetooth communication between two iOS devices. Obviously there is a lot more in the documentation, take this just as basics.

having issues?

We have a Questions and Answer section where you can ask your iOS Development questions to thousands of iOS Developers.

Ask Question

FREE Download!

Get your FREE Swift 2 Cheat Sheet and quick reference guide PDF download when you sign up to SwiftMonthly


Sharing is caring

If you enjoyed this tutorial, please help us and others by sharing using one of the social media buttons below.


Written by:

Dominik is a student developer who's making iPhone apps. Coming from the Czech Republic but studying in London, he writes about tips, tricks, tutorials and opinions he learns along his way as a dev. He is really passionate about both coding and writing. Original articles and tutorials can be found on the Authors website, check it out using the link below if you wish.

Comments

comments