The Ably LiveObjects plugin enables real-time collaborative data synchronization for the ably-cocoa SDK. LiveObjects provides a simple way to build collaborative applications with synchronized state across multiple clients in real-time. Built on Ably's core service, it abstracts complex details to enable efficient collaborative architectures.
Warning
This plugin is currently experimental. Breaking changes to its API may be made in minor or patch releases of ably-cocoa, without a major version bump; ably-cocoa's semantic versioning guarantees apply only to the Ably product.
Note
The plugin lives in the ably-cocoa repository and is versioned and released as part of ably-cocoa: add the ably-cocoa package to your project and select its AblyLiveObjects product. It was previously developed in the ably-liveobjects-swift-plugin repository; if you are coming from that package, see the migration guide.
Everything you need to get started with Ably LiveObjects:
- Learn about Ably LiveObjects.
- Getting started with LiveObjects in Swift.
- Explore the example app to see LiveObjects in action.
Ably aims to support a wide range of platforms. If you experience any compatibility issues, open an issue in the repository or contact Ably support.
This plugin supports the following platforms:
| Platform | Support |
|---|---|
| iOS | >= 14.0 |
| macOS | >= 11.0 |
| tvOS | >= 14.0 |
Note
Xcode 16.3 or later is required.
After installing the plugin, pass it to the client via
ARTClientOptions, and fetch channels with the LiveObjects channel modes:
import Ably
import AblyLiveObjects
let clientOptions = ARTClientOptions(key: "your-ably-api-key")
clientOptions.plugins = [.liveObjects: AblyLiveObjects.Plugin.self]
let realtime = ARTRealtime(options: clientOptions)
// Fetch a channel, specifying the LiveObjects channel modes
let channelOptions = ARTRealtimeChannelOptions()
channelOptions.modes = [.objectPublish, .objectSubscribe]
let channel = realtime.channels.get("my-channel", options: channelOptions)
// `channel.object` is the entry point into the LiveObjects API. Attach the
// channel, then fetch the channel's root map once objects are synchronized:
let root = try await channel.object.get()As of ably-cocoa 1.3.0, the plugin is developed, versioned and released from the ably-cocoa repository as the AblyLiveObjects product of the ably-cocoa package. The standalone ably-liveobjects-swift-plugin package is deprecated: no further releases will be published from it, and its final release is 0.4.1. Migrating takes two steps.
- Remove the
ably-liveobjects-swift-pluginpackage dependency from your project. - Add (or update) the
ably-cocoapackage at version 1.3.0 or later, and select itsAblyLiveObjectsproduct for your target — see the installation instructions.
Your imports and plugin registration are unchanged:
import Ably
import AblyLiveObjects
let clientOptions = ARTClientOptions(key: "your-ably-api-key")
clientOptions.plugins = [.liveObjects: AblyLiveObjects.Plugin.self]Important
If you update ably-cocoa to 1.3.0 or later while the standalone package is still in your dependency graph, package resolution fails immediately with:
error: multiple packages ('ably-cocoa', 'ably-cocoa-plugin-support') declare targets with a conflicting name: '_AblyPluginSupportPrivate'; target names need to be unique across the package graph
error: multiple packages ('ably-cocoa', 'ably-liveobjects-swift-plugin') declare targets with a conflicting name: 'AblyLiveObjects'; target names need to be unique across the package graph
The fix is to remove the standalone package dependency, as described above.
ably-cocoa 1.3.0 replaces the instance-based API of the standalone plugin (last published in its 0.4.1 release) with the path-based API: instead of obtaining and operating on explicit LiveMap/LiveCounter instances, data is accessed and mutated through PathObjects — stable references to locations within the channel object that resolve to values dynamically at runtime. See the PathObject documentation.
The headline API changes:
| Standalone plugin (≤ 0.4.1) | ably-cocoa 1.3.0+ |
|---|---|
channel.objects, returning RealtimeObjects |
channel.object, returning RealtimeObject |
try await channel.objects.getRoot(), returning any LiveMap |
try await channel.object.get(), returning any LiveMapPathObject |
Operate on explicit LiveMap/LiveCounter instances |
Navigate with PathObjects: root.get(key:), then cast with asLiveMap() / asLiveCounter() / asPrimitive() |
For example:
// Standalone plugin (≤ 0.4.1) — instance-based
let root = try await channel.objects.getRoot()
try await root.set(key: "myKey", value: "myValue")
let value = try root.get(key: "myKey")?.stringValue
// ably-cocoa 1.3.0+ — path-based
let root = try await channel.object.get()
try await root.set(key: "myKey", value: "myValue")
let value = try root.get(key: "myKey").asPrimitive().value()?.stringValueA PathObject is purely navigational: it can be created before the data at its path exists, and it survives the object at its path being replaced — there is no need to re-fetch anything when the underlying object changes. The example app demonstrates the path-based API.
This repository contains an example app, written using SwiftUI, which demonstrates how to use the plugin. The code for this app is in the Example directory.
In order to allow the app to use modern SwiftUI features, it supports the following OS versions:
- macOS 14 and above
- iOS 17 and above
- tvOS 17 and above
To run the app:
- Open the
AblyLiveObjects.xcworkspaceworkspace in Xcode. - Follow the instructions inside the
Secrets.example.swiftfile to add your Ably API key to the example app. - Run the
AblyLiveObjectsExampletarget. If you wish to run it on an iOS or tvOS device, you'll need to set up code signing.
The plugin is released as part of ably-cocoa; see the ably-cocoa CHANGELOG for details of releases (and CHANGELOG.md for the historical releases of the standalone plugin package). You can also view all Ably releases on changelog.ably.com.
Read the CONTRIBUTING.md guidelines to contribute to Ably or share feedback or request a new feature.
For help or technical support, visit Ably's support page. You can also view the community-reported GitHub issues or raise one yourself.
