Message Persistence API for PubNub Cocoa Swift SDK

This SDK has been replaced by a new PubNub Swift SDK written purely in Swift. Check it out here

Message Persistence provides real-time access to the history of all messages published to PubNub. Each published message is timestamped to the nearest 10 nanoseconds and is stored across multiple availability zones in several geographical locations. Stored messages can be encrypted with AES-256 message encryption, ensuring that they are not readable while stored on PubNub's network. For more information, refer to Message Persistence.

Messages can be stored for a configurable duration or forever, as controlled by the retention policy that is configured on your account. The following options are available: 1 day, 7 days, 30 days, 3 months, 6 months, 1 year, or Unlimited.

You can retrieve the following:

  • Messages
  • Message actions
  • File Sharing (using File Sharing API)

History

Requires Message Persistence

This method requires that Message Persistence is enabled for your key in the Admin Portal. Read the support page on enabling add-on features on your keys.

This function fetches historical messages of a channel.

It is possible to control how messages are returned and in what order, for example you can:

  • Search for messages starting on the newest end of the timeline (default behavior - reverse = false)
  • Search for messages from the oldest end of the timeline by setting reverse to true.
  • Page through results by providing a startDate OR endDate timetoken.
  • Retrieve a slice of the time line by providing both a startDate AND endDate timetoken.
  • Limit the number of messages to a specific quantity using the limit parameter.
Start & End parameter usage clarity

If only the startDate parameter is specified (without endDate), you will receive messages that are older than and up to that startDate timetoken value. If only the endDate parameter is specified (without startDate) you will receive messages that match that endDate timetoken value and newer. Specifying values for both startDate and endDate parameters will return messages between those timetoken values (inclusive on the endDate value). Keep in mind that you will still receive a maximum of 100 messages even if there are more messages that meet the timetoken values. Iterative calls to history adjusting the startDate timetoken is necessary to page through the full set of results if more than 100 messages meet the timetoken values.

Method(s)

To run History you can use the following method(s) in the Swift SDK:

History with closure

open func historyForChannel(
_ channel: String,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).

History with dates and closure

open func historyForChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
startDateNSNumberNoTimetoken delimiting the start of time slice (exclusive) to pull messages from.
endDateNSNumberNoTimetoken delimiting the end of time slice (inclusive) to pull messages from.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).

History with dates, limit, and closure

open func historyForChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
limit: UInt,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
startDateNSNumberNoTimetoken delimiting the start of time slice (exclusive) to pull messages from.
endDateNSNumberNoTimetoken delimiting the end of time slice (inclusive) to pull messages from.
limitUIntYesSpecifies the number of historical messages to return.
default/maximum is 100.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).

History with dates, timetoken, and closure

open func historyForChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
includeTimeToken shouldIncludeTimeToken: Bool,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
startDateNSNumberNoTimetoken delimiting the start of time slice (exclusive) to pull messages from.
endDateNSNumberNoTimetoken delimiting the end of time slice (inclusive) to pull messages from.
shouldIncludeTimeTokenBoolYesIf true the message post timestamps will be included in the history response.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).

History with dates, limit, timetoken, and closure

open func historyForChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
limit: UInt,
includeTimeToken shouldIncludeTimeToken: Bool,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
startDateNSNumberNoTimetoken delimiting the start of time slice (exclusive) to pull messages from.
endDateNSNumberNoTimetoken delimiting the end of time slice (inclusive) to pull messages from.
limitUIntYesSpecifies the number of historical messages to return.
default/maximum is 100.
shouldIncludeTimeTokenBoolYesIf true the message post timestamps will be included in the history response.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).

History with dates, limit, and closure, in reverse order

open func historyForChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
limit: UInt,
reverse shouldReverseOrder: Bool,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
startDateNSNumberNoTimetoken delimiting the start of time slice (exclusive) to pull messages from.
endDateNSNumberNoTimetoken delimiting the end of time slice (inclusive) to pull messages from.
limitUIntYesSpecifies the number of historical messages to return.
Default/maximum is 100.
shouldReverseOrderBoolYesSetting to true will traverse the time line in reverse starting with the oldest message first.
Default is false. If both start and end arguments are provided, reverse is ignored and messages are returned starting with the newest message.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).

History with dates, limit, timetoken, and closure, in reverse order

open func historyForChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
limit: UInt,
reverse shouldReverseOrder: Bool,
includeTimeToken shouldIncludeTimeToken: Bool,
withCompletion closure: PubNub.PNHistoryCompletionBlock
)
ParameterTypeRequiredDescription
channelStringYesChannel name to retrieve the History information.
startDateNSNumberNoTimetoken delimiting the start of time slice (exclusive) to pull messages from.
endDateNSNumberNoTimetoken delimiting the end of time slice (inclusive) to pull messages from.
limitUIntYesSpecifies the number of historical messages to return. default/maximum is 100.
shouldReverseOrderBoolYesSetting to true will traverse the time line in reverse starting with the oldest message first. Default is false. If both start and end arguments are provided, reverse is ignored and messages are returned starting with the newest message.
shouldIncludeTimeTokenBoolYesIf true the message post timestamps will be included in the history response.
closurePNHistoryCompletionBlockYesThe completion closure has two arguments: result - in case of successful processing (data field will contain results of history request operation); status - in case if error occurred during request processing (errorData contains error information).
tip
Using the reverse parameter

Messages are always returned sorted in ascending time direction from history regardless of reverse. The reverse direction matters when you have more than 100 (or limit, if it's set) messages in the time interval, in which case reverse determines the end of the time interval from which it should start retrieving the messages.

Basic Usage

Retrieve the last 100 messages on a channel:

self.client.historyForChannel("history_channel", withCompletion: { (result, status) in

if status == nil {

/**
Handle downloaded history using:
result.data.start - oldest message time stamp in response
result.data.end - newest message time stamp in response
result.data.messages - list of messages
*/
}
else {

/**
Handle message history download error. Check 'category' property
show all 23 lines

Response

The response object which is returned by the client when the history API is used:

open class PNHistoryData : PNServiceData {

// Channel history messages.
open var messages: [Any] { get }
// History time frame start time.
open var start: NSNumber { get }
// History time frame end time.
open var end: NSNumber { get }
}

open class PNHistoryResult : PNResult {

// Stores reference on channel history request processing information.
open var data: PNHistoryData { get }
}

Other Examples

Use historyForChannel to retrieve the three oldest messages by retrieving from the time line in reverse

self.client.historyForChannel("my_channel", start: nil, end: nil, limit: 3,
reverse: true, withCompletion: { (result, status) in

if status == nil {

/**
Handle downloaded history using:
result.data.start - oldest message time stamp in response
result.data.end - newest message time stamp in response
result.data.messages - list of messages
*/
}
else {

/**
show all 24 lines
Response
[
["Pub1","Pub2","Pub3"],
13406746729185766,
13406746780720711
]

Use historyForChannel to retrieve messages newer than a given timetoken by paging from oldest message to newest message starting at a single point in time (exclusive)

let start = NSNumber(value: (13406746780720711 as CUnsignedLongLong))
self.client.historyForChannel("my_channel", start: start, end: nil, limit: 100,
reverse: true, withCompletion: { (result, status) in

if status == nil {

/**
Handle downloaded history using:
result.data.start - oldest message time stamp in response
result.data.end - newest message time stamp in response
result.data.messages - list of messages
*/
}
else {

show all 25 lines
Response
[
["Pub3","Pub4","Pub5"],
13406746780720711,
13406746845892666
]

Use historyForChannel to retrieve messages until a given timetoken by paging from newest message to oldest message until a specific end point in time (inclusive)

let end = NSNumber(value: (13406746780720711 as CUnsignedLongLong))
self.client.historyForChannel("my_channel", start: nil, end: end, limit: 100, reverse: true,
withCompletion: { (result, status) in

if status == nil {

/**
Handle downloaded history using:
result.data.start - oldest message time stamp in response
result.data.end - newest message time stamp in response
result.data.messages - list of messages
*/
}
else {

show all 25 lines
Response
[
["Pub3","Pub4","Pub5"],
13406746780720711,
13406746845892666
]

History Paging Example

Usage

You can call the method by passing 0 or a valid timetoken as the argument.

// Pull out all messages newer than message sent at 14395051270438477.
let date = NSNumber(value: (14395051270438477 as CUnsignedLongLong));
self.historyNewerThan(date, onChannel: "history_channel", withCompletion: { (messages) in

print("Messages from history: \(messages)")
})

func historyNewerThan(_ date: NSNumber, onChannel channel: String,
withCompletion closure: @escaping (Array<Any>) -> Void) {

var msgs: Array<Any> = []
self.historyNewerThan(date, onChannel: channel, withProgress: { (messages) in

msgs.append(contentsOf: messages)
if messages.count < 100 { closure(msgs) }
show all 46 lines

History (Builder Pattern)

This function fetches historical messages of a channel.

This method uses the builder pattern; you can omit any optional arguments.

Method(s)

To get channel history using the Builder pattern, use the following method(s) in the Swift SDK:

history().channels([String])
.limit(UInt)
.performWithCompletion(PubNub.PNHistoryCompletionBlock)
ParameterTypeRequiredDescription
channels[String]YesList of channels for which history should be returned.
limitUIntNoMaximum number of messages which should be returned for each channel. Default and maximum value is 100 for a single channel, 25 for multiple channels.
completionPNHistoryCompletionBlockYesHistory pull processing completion block which pass two arguments: result - in case of successful request processing data field will contain results of history request operation; status - in case if error occurred during request processing.
tip
Using the reverse parameter

Messages are always returned sorted in ascending time direction from history regardless of reverse. The reverse direction matters when you have more than 100 (or limit, if it's set) messages in the time interval, in which case reverse determines the end of the time interval from which it should start retrieving the messages.

Basic Usage

self.client.history().channels(["my_channel"]).limit(15).performWithCompletion({ (result, status) in

if status == nil {

/**
Handle downloaded history using:
result.data.channels - dictionary with channels' history. Each key is channel name and value is
list of fetched messages.
*/
}
else {

/**
Handle message history download error. Check 'category' property
to find out possible reason because of which request did fail.
show all 22 lines

Delete Messages from History

Requires Message Persistence

This method requires that Message Persistence is enabled for your key in the Admin Portal. Read the support page on enabling add-on features on your keys.

Removes the messages from the history of a specific channel.

Delete-From-History

There is a setting to accept delete from history requests for a key, which you must enable by checking the Enable Delete-From-History checkbox in the key settings for your key in the Admin Portal.

Requires Initialization with secret key.

Method(s)

To Delete Messages from History you can use the following method(s) in the Swift SDK.

open func deleteMessagesFromChannel(
_ channel: String,
start startDate: NSNumber?,
end endDate: NSNumber?,
withCompletion closure: PubNub.PNMessageDeleteCompletionBlock? = nil
)

Basic Usage

let startDate = NSNumber(value: (15101397027611671 as CUnsignedLongLong))
let endDate = NSNumber(value: (15101397427611671 as CUnsignedLongLong))
self.client.deleteMessagesFromChannel("channel", start: startDate, end: endDate, withCompletion: { (status) in

if !status.isError {
// Messages within specified time frame has been removed.
} else {
/**
* Handle message history download error. Check 'category' property to find out possible
* issue because of which request did fail.
*
* Request can be resent using: status.retry()
*/
}
})

Other Examples

Delete specific message from history

To delete a specific message, pass the publish timetoken (received from a successful publish) in the End parameter and timetoken +/- 1 in the Start parameter. For example, if 15526611838554310 is the publish timetoken, pass 15526611838554309 in Start and 15526611838554310 in End parameters respectively as shown in the following code snippet.

let startDate = NSNumber(value: (15526611838554310 as CUnsignedLongLong))
let endDate = NSNumber(value: (15526611838554309 as CUnsignedLongLong))
self.client.deleteMessagesFromChannel("channel", start: startDate, end: endDate, withCompletion: { (status) in

if !status.isError {
// Messages within specified time frame has been removed.
} else {
/**
* Handle message history download error. Check 'category' property to find out possible
* issue because of which request did fail.
*
* Request can be resent using: status.retry()
*/
}
})

Delete Messages from History (Builder Pattern)

Requires Message Persistence

This method requires that Message Persistence is enabled for your key in the Admin Portal. Read the support page on enabling add-on features on your keys.

Removes the messages from the history of a specific channel.

Delete-From-History

There is a setting to accept delete from history requests for a key, which you must enable by checking the Enable Delete-From-History checkbox in the key settings for your key in the Admin Portal.

Requires Initialization with secret key.

Method(s)

To Delete Messages from History you can use the following method(s) in the Swift SDK.

deleteMessage().channel(String)
.start(NSNumber?)
.end(NSNumber?)
.performWithCompletion(PubNub.PNMessageDeleteCompletionBlock? = nil)

Basic Usage

let startDate = NSNumber(value: (15101397027611671 as CUnsignedLongLong))
let endDate = NSNumber(value: (15101397427611671 as CUnsignedLongLong))
self.client.deleteMessage().channel("channel").start(startDate).end(endDate).performWithCompletion({ (status) in

if !status.isError {
// Messages within specified time frame has been removed.
} else {
/**
* Handle message history download error. Check 'category' property to find out possible
* issue because of which request did fail.
*
* Request can be resent using: status.retry()
*/
}
})

Message Counts

Requires Message Persistence

This method requires that Message Persistence is enabled for your key in the Admin Portal. Read the support page on enabling add-on features on your keys.

Returns the number of messages published on one or more channels since a given time. The count returned is the number of messages in history with a timetoken value greater than or equal to than the passed value in the timetokensparameter.

Unlimited message retention

For keys with unlimited message retention enabled, this method considers only messages published in the last 30 days.

Method(s)

You can use the following method(s) in the Swift SDK:

messageCounts().channels([String])
.timetokens([Int])
.performWithCompletion(PNMessageCountCompletionBlock)
ParameterTypeRequiredDefaultDescription
channels[String]YesThe channels to fetch the message count
timetokens[Int]YesList with single or multiple timetokens, where each timetoken position in correspond to target channel location in channel names list.
completionPNMessageCountCompletionBlockYesMessages count fetch completion closure which pass two arguments: result - in case of successful request processing data field will contain results of message count fetch operation; status - in case of error occurred during request processing.

Basic Usage

let timetoken = NSNumber(value: (15501015683744028 as CUnsignedLongLong))
self.client.messageCounts().channels(["unread-channel-1", "unread-channel-2"])
.timetokens([timetoken])
.performWithCompletion({ (result, status) in

if !status.isError {
// Client state retrieved number of messages for channels.
} else {
/**
Handle client state modification error. Check 'category' property
to find out possible reason because of which request did fail.
Review 'errorData' property (which has PNErrorData data type) of status
object to get additional information about issue.

Request can be resent using: status.retry()
show all 18 lines

Returns

Channels count

Channels without messages have a count of 0. Channels with 10,000 messages or more have a count of 10000.

open class PNMessageCountData : PNServiceData {

// Dictionary where each key is name of channel and value is number of messages in it.
var channels: [String:Int] { get }
}

open class PNMessageCountResult : PNResult {

// Message count request processing information.
var data: PNMessageCountData { get }
}

Other Examples

Retrieve count of messages using different timetokens for each channel

let timetoken = NSNumber(value: (15501015683744028 as CUnsignedLongLong))
let timetoken2 = NSNumber(value: (15501015683744130 as CUnsignedLongLong))
self.client.messageCounts().channels(["unread-channel-1", "unread-channel-2"])
.timetokens([timetoken, timetoken2])
.performWithCompletion({ (result, status) in

if !status.isError {
// Client state retrieved number of messages for channels.
} else {
/**
Handle client state modification error. Check 'category' property
to find out possible reason because of which request did fail.
Review 'errorData' property (which has PNErrorData data type) of status
object to get additional information about issue.

show all 19 lines
Last updated on