Data components for PubNub Chat Components for iOS
Data components are responsible for managing data between the UI Components and the persistence layer. They also interact with the PubNub service by sending and receiving messages and signals.
Available components include:
Overview
PubNub Chat Components for iOS utilize several layers of configurable data to drive the functionality found in the UI Components. The goal of the data layer is to provide a simple and robust foundation that can be used across any chat implementation. The two main forms of data used by the components are managed and network objects.
Managed data
PubNub Chat Components for iOS rely on Core Data - an Apple framework to manage the model layer of the application - to provide a persistent, abstracted, and reliable local state to the UI Components.
This is achieved by defining data schemas and relationships inside a Managed Object Model. There is also a pre-configured set of managed entities provided by default to support rapid prototyping.
Network data
A drawback of using Core Data managed objects is they can only be handled on the main queue of the application. To avoid any issues or errors while using concurrency, the managed objects are able to be converted to and from network object types. The objects attempt to mirror the default managed object schema, but can be further customized to match any schema that's needed by the application.
Network objects are most commonly used when interacting with PubNub APIs, but should be used whenever the applications might use multiple threads.
Data flow
The typical data flow through the components revolves around storing incoming data into the Core Data instance and updating that data automatically in UI Components if the data matches the UI Components population query.
-
The PubNub APIs and Events return network data that can be stored directly in Core Data using the appropriate
DataProvider
methods found insideChatProvider
. -
The UI Components use
NSFetchedResultsController
to createNSPredicate
against the stored (managed) data. This controller automatically updates the component's data source if the new matching data is added, updated, or removed. -
The UI Components provide actions that can be configured to call PubNub APIs through
DataProvider
or update existing objects and store the result.
Data payloads
PubNub Chat Components for iOS enforce you to use the unified JSON schemas (data models) for such common entity types as users, channels, and messages when transferring data over the PubNub network. These common data payloads allow you to create cross-platform applications and ensure that such applications developed in different technologies (Swift, Kotlin, or JavaScript) communicate with one another properly, avoiding any unexpected errors.
Validate your payload
To avoid any parsing errors, validate the data payload you prepared for users, channels, and messages in an online validator.
Users
Follow this schema for the user data in your apps:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"description": "User of a chat application",
"properties": {
"id": {
"description": "Unique identifier for a user",
"type": "string"
},
"name": {
"description": "Name of the user that you can display in the UI",
"type": "string"
},
"email": {
show all 58 linesExample:
{
"id": "some-user-id",
"name": "Jane Doe",
"email": "jane.doe@example.com",
"externalId": "some-external-user-id",
"profileUrl": "https://randomuser.me/api/portraits/men/1.jpg",
"type": "default",
"status": "default",
"custom": {
"description": "Office Assistant",
},
"eTag": "AYGyoY3gre71eA",
"updated": "2020-09-23T09:23:34.598494Z"
}
Channels
Follow this schema for the channel data in your apps:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Channel",
"description": "Channel in the chat application",
"type": "object",
"properties": {
"id": {
"description": "Unique identifier for a channel",
"type": "string"
},
"name": {
"description": "Name of the channel that you can display in the UI",
"type": "string"
},
"description": {
show all 50 linesExample:
{
"id": "some-channel-id",
"name": "Off-topic",
"description": "Off-topic channel for random chatter and fun",
"type": "default",
"status": "default",
"custom": {
"profileUrl": "https://www.gravatar.com/avatar/149e60f311749f2a7c6515f7b34?s=256&d=identicon"
},
"eTag": "AbOx6N+6vu3zoAE",
"updated": "2020-09-23T09:23:37.175764Z"
}
Messages
Follow this schema for the message data in your apps:
Supported message types
PubNub Chat Components for iOS support only text message data types.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Message Content",
"description": "Message content in the chat application",
"type": "object",
"properties": {
"id": {
"description": "Unique identifier for a message. Use the UUID v4 algorithm.",
"type": "string"
},
"text": {
"description": "Text of the message that you can display in the UI",
"type": "string"
},
"contentType": {
show all 34 linesExample:
{
"id": "6da72b98-e211-4724-aad4-e0fb9f08999f",
"text": "Let's sync on the topic in this thread.",
"contentType": "none",
"content": {},
"custom": {},
"createdAt": "2022-05-10T14:48:00.000Z"
}
Channel
A channel is commonly viewed as a collection of associated users with a specific purpose or goal. A channel could be created for direct communication between two or more users, a group of users, or other use case-specific scenarios.
Managed data
The default Managed Object Model inside the Chat Components defines a Core Data NSManagedObject
named PubNubManagedChannel
.
If a custom Managed Object Model is used, an NSManagedObject
entity must implement the ManagedChatChannel
protocol before it can be used by the Chat Components framework.
Managed channel
The PubNubManagedChannel
entity is a CoreData managed Channel
class used whenever a ChatChannel
needs to be stored locally. It is defined with the following attributes:
Name | Type | Description |
---|---|---|
id | String | Unique identifier for the object. |
name | String? | Name of the channel. |
type | String | Functional type of the channel. The default value is set to "default" . |
status | String? | Status of the channel. |
details | String? | Channel details you can display alongside the name. |
avatarURL | URL? | URL to a channel avatar that you can display in the UI. |
custom | Data | Custom key value pairs that can be stored with the channel. |
lastUpdated | Date? | Last time the remote object was changed. This field references the updated field from ChatChannel . |
eTag | String? | Caching value that changes whenever the remote object changes. |
memberCount | Int | Total number of members that are currently active on the channel. |
Relationships
The PubNubManagedChannel
entity has relationships with the following entities:
Name | Type | Description |
---|---|---|
members | Set<PubNubManagedMember> | Entity that connects to the users of a channel. |
messages | Set<PubNubManagedMessage> | Entity that connects to the messages of a channel. |
Managed channel protocol
To allow for a custom Managed Object Model, the ManagedChatChannel
protocol is used when referring to the managed object.
The protocol requires the following properties and methods:
-
pubnubChannelID
Identifier used when interacting with PubNub APIs. It can be different from the primary key ID used by the managed object.
var pubnubChannelID: String { get }
-
convert()
Converts the managed object to a network object with the appropriately typed custom channel data.
func convert<Custom: ChannelCustomData>() -> ChatChannel<Custom>
Returns
The base network object transformed to use the specified ChannelCustomData
.
-
insertOrUpdate(channel:into:)
Inserts or updates the managed object from a network object.
@discardableResult
static func insertOrUpdate<Custom: ChannelCustomData>(
channel: ChatChannel<Custom>,
into context: NSManagedObjectContext
) throws -> Self
Parameters
Name | Type | Description |
---|---|---|
channel | ChatChannel<ChannelCustomData> | ChatChannel to be updated or inserted. |
into | NSManagedObjectContext | Core Data context where the object is inserted or updated. |
Returns
The managed object that was inserted or updated.
Observing the NSManagedObjectContextDidSave notification will indicate whether a new managed object was created or an existing object was updated.
patch(usingPatch:into:)
@discardableResult
static func patch<Custom: ChannelCustomData>(
usingPatch patcher: ChatChannel<Custom>.Patcher,
into context: NSManagedObjectContext
) throws -> Self
Parameters
Name | Type | Description |
---|---|---|
usingPatch | ChatChannel<ChannelCustomData>.Patcher | ChatChannel.Patcher changeset that is applied to an existing channel if one exists. |
into | NSManagedObjectContext | Core Data context where the object is inserted or updated. |
Returns
The managed object that was updated.
Observing the NSManagedObjectContextDidSave notification will indicate whether an existing object was updated.
-
remove(channelId:from:)
Removes a managed object matching the
channelId
parameter.@discardableResult
static func remove(
channelId: String,
from context: NSManagedObjectContext
) -> Self?
Parameters
Name | Type | Description |
---|---|---|
channelId | String | Unique identifier for the channel. |
from | NSManagedObjectContext | Core Data context where the object is removed. |
Returns
The managed object that was removed.
Observing the NSManagedObjectContextDidSave notification will indicate whether a managed object was removed.
-
channelBy(channelID:)
Creates
NSFetchRequest
that gets a channel matching thechannelId
parameter.static func channelBy(channelID: String) -> NSFetchRequest<Self>
Parameters
Name | Type | Description |
---|---|---|
channelID | String | Unique identifier for the channel. |
Returns
NSFetchRequest
whose predicate is set to get the channel that matches the channelID
parameter.
Network data
The generic ChatChannel
class contains the channel payload fields and is used whenever a Swift PubNub API requires a Space
object.
Name | Type | Description |
---|---|---|
id | String | Unique identifier for the object. |
name | String? | Name of the channel. |
type | String | Functional type of the channel. The default value is set to "default" . |
status | String? | Status of the channel. |
details | String? | Channel details you can display alongside the name. |
avatarURL | URL? | URL to a channel avatar that you can display in the UI. This field references the profileUrl field from the channel payload specification. |
updated | Date? | Last time the remote object was changed. |
eTag | String? | Caching value that changes whenever the remote object changes. |
custom | ChannelCustomData | Custom key value pairs that can be stored with the channel. |
Custom channel data
Implement the ChannelCustomData
protocol to provide custom data to the generic ChatChannel
class.
By default, all custom data is implemented as an empty object VoidCustomData
.
The default implementation of ChatChannel
is a typealias of the following:
public typealias PubNubChatChannel = ChatChannel<VoidCustomData>
APIs
patch(:)
Patches the properties of an existing ChatUser
from a real-time changeset.
public func patch(
_ patcher: ChatChannel<Custom>.Patcher
) -> ChatChannel<Custom>
Parameters
Name | Type | Description |
---|---|---|
user | ChatChannel<Custom>.Patcher | Channel changeset that will be applied to an existing ChatChannel . |
Returns
An updated ChatChannel
if the Patcher
was able to perform the update, otherwise the duplicate ChatChannel
.
Data provider actions
DataProvider
contains several convenience methods that streamline the ability to fetch and manage channel data. You can access DataProvider
through ChatProvider
.
-
load()
Inserts or updates a list of channels in the Core Data store batching based on the supplied
batchSize
.public func load(
channels: [ChatChannel<ModelData.Channel>],
batchSize: Int = 256,
batchHandler: (([ChatChannel<ModelData.Channel>], Error?) -> Void)? = nil,
completion: (() -> Void)? = nil
)
Parameters
Name | Type | Description |
---|---|---|
channels | [ChatChannel<ModelData.Channel>] | Channels to store. |
batchSize | Int | Size of each chunk of channels to store. |
batchHandler | (([ChatChannel<ModelData.Channel>], Error?) -> Void)? | Closure called after storing each batch. |
completion | (() -> Void)? | Closure called after storing all channels. |
-
removeStoredChannel()
Removes a managed channel matching the supplied
channelId
.public func removeStoredChannel(
channelId: String,
completion: ((Error?) -> Void)? = nil
)
Parameters
Name | Type | Description |
---|---|---|
channelId | String | Unique identifier for the channel. |
completion | ((Error?) -> Void)? | Closure called after removing the channel. |
-
syncRemoteChannel()
Calls the
fetch(channel:)
PubNub endpoint and stores the response inside the Core Data store.public func syncRemoteChannel(
_ request: ChatChannelRequest<ModelData.Channel>,
completion: ((Result<ChatChannel<ModelData.Channel>, Error>) -> Void)? = nil
)
Parameters
Name | Type | Description |
---|---|---|
_ request | ChatChannelRequest<ModelData.Channel> | Request object that sets the PubNub API method parameters. |
completion | ((Result<ChatChannel<ModelData.Channel>, Error>) -> Void)? | Result of either the fetched and stored channel or an Error . |
syncRemoteChannelsPaginated()
Calls the fetchPagesPublisher(channels:)
PubNub endpoint and stores the response inside the Core Data store.
public func syncRemoteChannelsPaginated(
_ request: ChannelsFetchRequest,
pageHandler: (([ChatChannel<ModelData.Channel>], ChannelsFetchRequest?, Error?) -> Void)? = nil,
completion: ((PaginationError<ChannelsFetchRequest>?) -> Void)? = nil
)
Parameters
Name | Type | Description |
---|---|---|
_ request | ChannelsFetchRequest | Request object that sets the PubNub API method parameters. |
pageHandler | (([ChatChannel<ModelData.Channel>], ChannelsFetchRequest?, Error?) -> Void)? | The latest batch of ChatChannel that was fetched and stored. |
completion | ((PaginationError<ChannelsFetchRequest>?) -> Void)? | Result of either the fetched and stored channels (with the next request for pagination) or an Error . |
createRemoteChannel()
Calls the create(channel:)
PubNub endpoint and stores the response inside the Core Data store.
public func createRemoteChannel(
_ request: ChatChannelRequest<ModelData.Channel>,
completion: ((Result<ChatChannel<ModelData.Channel>, Error>) -> Void)? = nil
)
Parameters
Name | Type | Description |
---|---|---|
_ request | ChatChannelRequest<ModelData.Channel> | Request object that sets the PubNub API method parameters. |
completion | ((Result<ChatChannel<ModelData.Channel>, Error>) -> Void)? | Result of either the fetched and stored channels (with the next request for pagination) or an Error . |
updateRemoteChannel()
Calls the update(channel:)
PubNub endpoint and stores the response inside the Core Data store.
public func updateRemoteChannel(
_ request: ChatChannelRequest<ModelData.Channel>,
completion: ((Result<ChatChannel<ModelData.Channel>, Error>) -> Void)? = nil
)
Parameters
Name | Type | Description |
---|---|---|
_ request | ChatChannelRequest<ModelData.Channel> | Request object that sets the PubNub API method parameters. |
completion | ((Result<ChatChannel<ModelData.Channel>, Error>) -> Void)? | Result of either the fetched and stored channel or an Error . |
removeRemoteChannel()
Calls the remove(channel:)
PubNub endpoint and stores the response inside the Core Data store.
public func removeRemoteChannel(
_ request: ChatChannelRequest<ModelData.Channel>,
completion: ((Result<Void, Error>) -> Void)?
)
Parameters
Name | Type | Description |
---|---|---|
_ request | ChatChannelRequest<ModelData.Channel> | Request object that sets the PubNub API method parameters. |
completion | ((Result<Void, Error>) -> Void)? | Result of either the fetched and stored channel or an Error . |
User
A user is an individual that's using the chat application and can be associated with both channels (through members) and messages.
Managed data
The default Managed Object Model inside the Chat Components defines a Core Data NSManagedObject
named PubNubManagedUser
.
If a custom Managed Object Model is used, then an NSManagedObject
entity must implement the ManagedChatUser
protocol before it can be used by the Chat Components framework.
Managed user
The PubNubManagedUser
entity is a CoreData managed User
class used whenever a ChatUser
needs to be stored locally. It is defined with the following attributes:
Name | Type | Description |
---|---|---|
id | String | Unique identifier for the object. |
name | String? | Name of the channel. |
type | String | Functional type of the user. The default value is set to "default" . |
status | String? | Status of the user. |
externalId | String? | External identifier for the object. |
avatarURL | URL? | URL to a user avatar that you can display in the UI. |
email | String? | Email address for the user. |
custom | Data | Custom key value pairs that can be stored with the user. |
lastUpdated | Date? | Last time the remote object was changed. This field references the updated field from ChatUser . |
eTag | String? | Caching value that changes whenever the remote object changes. |
Relationships
The PubNubManagedUser
entity has relationships with the following entities:
Name | Type | Description |
---|---|---|
memberships | Set<PubNubManagedMember> | Entity that connects to the users of a channel. |
messages | Set<PubNubManagedMessage> | Entity that connects to the messages of a channel. |
Managed user protocol
To allow for a custom Managed Object Model, the ManagedChatUser
protocol is used when referring to the managed object.
The protocol requires the following properties and methods:
-
pubnubUserID
Identifier used when interacting with PubNub APIs. It can be different from the primary key ID used by the managed object.
var pubnubUserID: String { get }
-
convert()
Converts the managed object to a network object with the appropriately typed custom user data.
func convert<Custom: UserCustomData>() -> ChatUser<Custom>
Returns
The base network object transformed to use the specified UserCustomData
.
-
insertOrUpdate(user:into:)
Inserts or updates the managed object from a network object.
@discardableResult
static func insertOrUpdate<Custom: UserCustomData>(
user: ChatUser<Custom>,
into context: NSManagedObjectContext
) throws -> Self
Parameters
Name | Type | Description |
---|---|---|
user | ChatUser<UserCustomData> | ChatUser to be updated or inserted. |
into | NSManagedObjectContext | Core Data context where the object is inserted or updated. |
Returns
The managed object that was inserted or updated.
Observing the NSManagedObjectContextDidSave notification will indicate whether a new managed object was created or an existing object was updated.
patch(usingPatch:into:)
@discardableResult
static func patch<Custom: UserCustomData>(
usingPatch patcher: ChatUser<Custom>.Patcher,
into context: NSManagedObjectContext
) throws -> Self
Parameters
Name | Type | Description |
---|---|---|
usingPatch | ChatUser<UserCustomData>.Patcher | ChatUser.Patcher changeset that is applied to an existing user if one exists. |
into | NSManagedObjectContext | Core Data context where the object is inserted or updated. |
Returns
The managed object that was updated.
Observing the NSManagedObjectContextDidSave notification will indicate whether an existing object was updated.
-
remove(userId:from:)
Removes a managed object matching the
userId
parameter.@discardableResult
static func remove(
userId: String,
from context: NSManagedObjectContext
) -> Self?
Parameters
Name | Type | Description |
---|---|---|
userId | String | Unique identifier for the user. |
from | NSManagedObjectContext | Core Data context where the object is removed. |
Returns
The managed object that was removed.
Observing the NSManagedObjectContextDidSave notification will indicate whether a managed object was removed.
-
userBy(userId:)
Creates
NSFetchRequest
that getsManagedChatUser
matching theuserId
parameter.static func userBy(userId: String) -> NSFetchRequest<Self>
Parameters
Name | Type | Description |
---|---|---|
userId | String | Unique identifier for ManagedChatUser . |
Returns
NSFetchRequest
whose predicate is set to get ManagedChatUser
that matches the userId
parameter.
Network data
The generic ChatUser
class contains the user payload fields and is used whenever a Swift PubNub API requires a User
object.
Name | Type | Description |
---|---|---|
id | String | Unique identifier for the object. |
name | String? | Name of the channel. |
type | String | Functional type of the user. The default value is set to "default" . |
status | String? | Status of the user. |
externalId | String? | External identifier for the object. |
avatarURL | URL? | URL to a user avatar that you can display in the UI. This field references the profileUrl field from the user payload specification. |
email | String? | Email address for the user. |
updated | Date? | Last time the remote object was changed. |
eTag | String? | Caching value that changes whenever the remote object changes. |
custom | UserCustomData | Custom key value pairs that can be stored with the user. |
Custom user data
Implement the UserCustomData
protocol to provide custom data to the generic ChatUser
class.
By default, all custom data is implemented as an empty object VoidCustomData
.
The default implementation of ChatUser
is a typealias of the following:
public typealias PubNubChatUser = ChatUser<VoidCustomData>