Shared Spaces with CanIO on iOS

CanIO enables your app to use "Shared Spaces" - data objects which are created by one peer in a local peer-to-peer network, which can be accessed and synced across multiple peers. This is a typical flow describing usage of a shared space:

  1. One of the peers creates a shared space and populates it with an initial dataset.
  2. Other peers in the area detect the space and join it; All the data populated by the first peer is synced and can be accessed by the other peers.
  3. The peer that owns the space or the other peers can make changes in the dataset; These changes are synced between all of the peers with access to the space.

The following document explains how to set up and use shared spaces in your app for simplified peer-to-peer communication:

Setting up the local peer-to-peer network

Before setting up and using shared spaces, your app should initialize CanIO services, and discover other local peers. Please read the Peer-to-peer networking guide on how to initialize CanIO services, advertise your local peer, and discover other peers. There is no need to create CanIO requests and responses when using shared spaces, as the shared space itself handles all communications and data transfer.

CanIOSharedManager class

The CanIOSharedSpaceManager singleton class is a central interface for interacting with shared spaces, and is used to create new shared spaces and access existing ones. This class also defines a protocol CanIOSharedSpaceManagerDelegate, which defines a set of delegate methods which are called around shared space related events.

Creating a shared space

Any peer in the local peer-to-peer network can create any number of shared spaces. The peer that created the space is defined as the space owner. Other peers in the network who have discovered this peer will be notified about the new space and can join to choose it, and the owner can also invite peers to join. Any changes made by the peers to the shared space data will be synced through the owner to the other peers.

CanIOSharedSpace also defines a protocol called CanIOSharedSpaceDelegate, which defines a set of methods around events related to this specific space.

To create a new shared space:

CanIOSharedSpace *newSpace = [CanIOSharedSpaceManager sharedManager] createSpaceWithName:@"My new space"];
newSpace.delegate = self;

Discovering shared spaces

CanIOPeer has a property called spacesList. This is an array containing a set of NSDictionary objects, each describing the spaces offered by this peer. Each space has a "title" value with its title, and a "space_uuid" value with its UUID. The UUID is used to join the space.

When a new shared space is created by a discovered peer, the spacesList array will be updated and the following CanIOManagerDelegate delegate method will be called:

- (void)canioManager:(CanIOManager *)canioManager didUpdateSpacesForPeer:(CanIOPeer *)peer;

Joining a shared space

Once the local peer has discovered a shared space, it can join it. To join a shared space using its UUID. To join a shared space:

[[CanIOSharedSpaceManager sharedManager] joinSpaceWithUUID:spaceUUID ownedByPeer:spacePeer];

The space owner will be notified of the new peer joining the space through the following CanIOSharedSpaceDelegate method:

- (void)sharedSpace:(CanIOSharedSpace *)space peerDidJoin:(CanIOPeer *)peer;

Once your local peer has successfully joined the space, or failed to join the space, one of the following CanIOSharedSpaceDelegate method will be called:

- (void)sharedSpaceManager:(CanIOSharedSpaceManager *)manager didJoinSpace:(CanIOSharedSpace *)space;
- (void)sharedSpaceManager:(CanIOSharedSpaceManager *)manager failedToJoinSpaceWithUUID:(NSString *)UUID;

If joining the space was successful, a new space object is created and passed with the delegate method. You can now use this object to access the space's information, or make changes to it which will be synced back to the owner and other members of the space.

Creating shared space objects

Each shared space can contain many different objects, each with a different type. Any object created in a space will be visible and synced to other peers in your peer-to-peer network.

Any object you create will be based on one of the subclasses of CanIOSharedObject. One of the most common shared object types is a CanIOSharedObjectJSON, which is a wrapper for a shared JSON object. To create a new JSON object and add it to your space:

CanIOSharedObjectJSON *myJsonObject = [CanIOSharedObjectJSON alloc] init]
[mySharedSpace addObject:myJsonObject withName:@"my_object_name"];

Editing a shared object

Each CanIOSharedObject class offers a set of methods to edit its contents, depending on the content type. For a CanIOSharedObjectJSON, use the setObject:ForPath: method to set the object for a certain JSON path. You can use any objects which can be represented in JSON format, such as dictionaries, arrays and strings.

Here is an example of setting the username of a user with an ID of 1. If the element at a certain point in the path is a hash, the path segment will be used as the hash key. If the element at a certain point is an array, the path segment will be used as the id of the object in the array.

[myJsonObject setObject:@"Jenny Smith" forPath:@"/contacts/1/name"];

The underlying JSON object would look like:

{
    "contacts" : [
        {
            "id": "1",
            "name": "Michael Smith"
        },
        {
            "id"; "2",
            "name": "John Doe"
        }
    ]
}

Getting notified about changes in an object

If one of the other peers in the space has made a change in the space, the following CanIOSharedSpace delegate method will be called:

- (void)sharedSpace:(CanIOSharedSpace *)space didUpdateDataForObject:(CanIOSharedObject *)object atPath:(NSString *)path;

You can inspect the path to understand which element within the space was changed, and update your app accordingly. You can access the space's underlying json in the form of an NSDictionary through the json property.

NSDictionary *json = myJsonObject.json;

You can use the space's objectForPath: method to access an object at a specific path, and to quickly access the object which was edited:

NSString *name = [myJsonObject objectForPath:@"/contacts/1/name"];

Inviting a peer to a shared space

Peers can join a shared space, but can also be invited to the space by one of its members.

To invite a peer to a space, call the invitePeer method on your CanIOSharedSpace object:

[mySpace invitePeer:myPeer];

The invited peer's CanIOSharedSpaceDelegate will receive the following call:

- (void)sharedSpaceManager:(CanIOSharedSpaceManager *)manager didReceiveSharedSpaceInvitation:(CanIOSharedSpaceInvitation *)invitation;

The CanIOSharedSpaceInvitation object is used to accept or reject the invitation. Your local peer can accept the invitation and receive a reference to the space they have joined by using:

CanIOSharedSpace *invitedSpace = [invitation accept];

Or reject the invitation

[invitation reject];

The inviting peer's CanIOSharedSpaceManagerDelegate will receive one of the following calls, notifying them of the invitation resolution:

- (void)sharedSpace:(CanIOSharedSpace *)space peerDidAcceptInvitation:(CanIOPeer *)peer;
- (void)sharedSpace:(CanIOSharedSpace *)space peerDidRejectInvitation:(CanIOPeer *)peer;