Publish/Subscribe 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
Publish
Description
The publish()
function is used to send a message to all subscribers of a channel. To publish a message you must first specify a valid publishKey
at initialization. A successfully published message is replicated across the PubNub Real-Time Network and sent simultaneously to all subscribed clients on a channel.
Messages in transit can be secured from potential eavesdroppers with SSL/TLS by setting ssl to true during initialization.
Publish Anytime
It's not required to be subscribed to a channel in order to publish to that channel.
Message Data:
The message argument can contain any JSON serializable data, including: Objects, Arrays, Ints and Strings. data
should not contain special Swift classes or functions as these will not serialize. String content can include any single-byte or multi-byte UTF-8 character.
Don't JSON serialize!
It is important to note that you should not JSON serialize when sending signals/messages via PUBNUB. Why? Because the serialization is done for you automatically. Instead just pass the full object as the message payload. PubNub takes care of everything for you.
Message Size:
The maximum number of characters per message is 32 KiB by default. The maximum message size is based on the final escaped character count, including the channel name. An ideal message size is under 1800 bytes which allows a message to be compressed and sent using single IP datagram (1.5 KiB) providing optimal network performance.
If the message you publish exceeds the configured size, you will receive the following message:
Message Too Large Error
["PUBLISHED",[0,"Message Too Large","13524237335750949"]]
For further details please check: https://support.pubnub.com/hc/en-us/articles/360051495932-Calculating-Message-Payload-Size-Before-Publish
Message Publish Rate:
Messages can be published as fast as bandwidth conditions will allow. There is a soft limit based on max throughput since messages will be discarded if the subscriber can't keep pace with the publisher.
For example, if 200 messages are published simultaneously before a subscriber has had a chance to receive any messages, the subscriber may not receive the first 100 messages because the message queue has a limit of only 100 messages stored in memory.
Publishing to Multiple Channels:
It is not possible to publish a message to multiple channels simultaneously. The message must be published to one channel at a time.
Publishing Messages Reliably:
There are some best practices to ensure messages are delivered when publishing to a channel:
- Publish to any given channel in a serial manner (not concurrently).
- Check that the return code is success (e.g.
[1,"Sent","136074940..."]
) - Publish the next message only after receiving a success return code.
- If a failure code is returned (
[0,"blah","<timetoken>"]
), retry the publish. - Avoid exceeding the in-memory queue's capacity of 100 messages. An overflow situation (aka missed messages) can occur if slow subscribers fail to keep up with the publish pace in a given period of time.
- Throttle publish bursts in accordance with your app's latency needs e.g. Publish no faster than 5 msgs per second to any one channel.
Method(s)
To Publish a message
you can use the following method(s) in the Swift SDK:
open func publish(_ message: Any, toChannel channel: String, withCompletion block: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel name to publish messages to. closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, compressed: Bool, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.compressed
Bool Yes If true
the message will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, storeInHistory shouldStore: Bool, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, storeInHistory shouldStore: Bool, compressed: Bool, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.compressed
Bool Yes If true
the message will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads for different vendors (Apple with aps
key and Google withgcm
). Either payloads or message should be provided.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, compressed: Bool, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads for different vendors (Apple with aps
key and Google withgcm
). Either payloads or message should be provided.compressed
Bool Yes If true
the message will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, storeInHistory shouldStore: Bool, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads for different vendors (Apple with aps
key and Google withgcm
). Either payloads or message should be provided.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, storeInHistory shouldStore: Bool, compressed: Bool, withCompletion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message may be any valid foundation object ( String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads for different vendors (Apple with aps
key and Google withgcm
). Either payloads or message should be provided.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.compressed
Bool Yes If true
the message will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, compressed: Bool, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.compressed
Bool Yes If true
themessage
will becompressed
and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, storeInHistory shouldStore: Bool, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any, toChannel channel: String, storeInHistory shouldStore: Bool, compressed: Bool, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any Yes The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.compressed
Bool Yes If true
themessage
will becompressed
and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads
for different vendors (Apple withaps
key and Google withgcm
). Eitherpayloads
ormessage
should be provided.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, compressed: Bool, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads
for different vendors (Apple withaps
key and Google withgcm
). Eitherpayloads
ormessage
should be provided.compressed
Bool Yes If true
themessage
will becompressed
and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, storeInHistory shouldStore: Bool, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message
may be any valid foundationobject
(String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads
for different vendors (Apple withaps
key and Google withgcm
). Eitherpayloads
ormessage
should be provided.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).open func publish(_ message: Any?, toChannel channel: String, mobilePushPayload payloads: [String : Any]?, storeInHistory shouldStore: Bool, compressed: Bool, withMetadata metadata: [String : Any]?, completion closure: PubNub.PNPublishCompletionBlock? = nil)
Parameter Type Required Description message
Any No The message
may be any valid foundation object (String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name to publish messages to.payloads
[String : Any] No Dictionary with payloads
for different vendors (Apple withaps
key and Google withgcm
). Eitherpayloads
ormessage
should be provided.shouldStore
Bool Yes If false
the messages will not be stored in history, defaulttrue
.compressed
Bool Yes If true
themessage
will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.metadata
[String : Any] No NSDictionary
with values which should be used byPubNub
service to filter messages.closure
PNPublishCompletionBlock No The completion closure
which will be called when the processing is complete, has one argument: -request
status reports thepublish
was successful or not (errorData
contains error information in case of failure).
Basic Usage
Publish a message to a channel:
self.client.publish("Hello from the PubNub Swift SDK", toChannel: "my_channel",
compressed: false, withCompletion: { (status) in
if !status.isError {
// Message successfully published to specified channel.
}
else{
/**
Handle message publish 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()
*/
}
})
Note
Before running the above publish example, either using the Debug Console or in a separate script running in a separate terminal window, subscribe to the same channel that is being published to.
Response
Response objects which is returned by client when publish API is used:
open class PNPublishData : PNServiceData {
open var timetoken: NSNumber { get }
open var information: String { get }
}
open class PNPublishStatus : PNAcknowledgmentStatus {
open var data: PNPublishData { get }
}
Other Examples
Publish a JSON serialized message
self.client.publish(["Dictionary": ["with", "array", "as", "value"]], toChannel: "pubnub", withMetadata: ["senderID" : "bob"], completion: { (status) in if !status.isError { // Message successfully published to specified channel. } else{ /** Handle message publish 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() */ } })
-
self.client.publish("Hello from the PubNub Swift", toChannel: "chat_channel", withMetadata: ["senderID" : "bob"], completion: { (status) in if !status.isError { // Message successfully published to specified channel. } else{ /** Handle message publish 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() */ } })
Publish (Builder Pattern)
Description
This function publishes a message on a channel.
Note
This method uses the builder pattern, you can remove the args which are optional.
Method(s)
To run Publish Builder
you can use the following method(s) in the Swift SDK:
publish().message(Any).channel(NSString).shouldStore(Bool).replicate(Bool).compress(Bool).ttl(UInt).payloads([String : Any]).metadata([String : Any]).performWithCompletion(PNPublishCompletionBlock)
Parameter Type Required Description message
Any No The message
may be any valid foundation object (String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name topublish
messages to.shouldStore
Bool No If false
the messages will not be stored in history.
Defaulttrue
.replicate
Bool No Specify whether published message
should be replicated across the PubNub Real-Time Network and sent simultaneously to all subscribed clients on achannel
.compress
Bool No If true
themessage
will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.ttl
UInteger No Specify for how many hours published message
should be stored.payloads
[String : Any] No Dictionary with payloads
for different vendors (Apple withaps
key and Google withgcm
). Eitherpayloads
ormessage
should be provided.metadata
[String : Any] No Dictionary
with values which should be used byPubNub
service to filter messages.block
PNPublishCompletionBlock No The completion block
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).
Basic Usage
Publish message which will be stored in channel's storage for next 16 hours.
self.client.publish().channel("my_channel").message("Hello from the PubNub Swift SDK").compress(false).ttl(16).performWithCompletion({ (status) in
if !status.isError {
// Message successfully published to specified channel.
}
else{
/**
Handle message publish 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()
*/
}
});
Fire (Builder Pattern)
Description
The fire endpoint allows the client to send a message to BLOCKS Event Handlers. These messages will go directly to any Event Handlers registered on the channel that you fire to and will trigger their execution. The content of the fired request will be available for processing within the Event Handler. The message sent via fire()
is not replicated, and so will not be received by any subscribers to the channel. The message is also not stored in history.
Note
This method uses the builder pattern, you can remove the args which are optional.
Method(s)
To Fire a message
you can use the following method(s) in the Swift SDK:
fire().message(Any).channel(NSString).compress(Bool).ttl(UInt).payloads([String : Any]).metadata([String : Any]).performWithCompletion(PNPublishCompletionBlock)
Parameter Type Required Description message
Any No The message
may be any valid foundation object (String
,NSNumber
,Array
,Dictionary
).channel
String Yes Specifies channel
name topublish
messages to.compress
Bool No If true
themessage
will be compressed and sent with request body instead of the URI. Compression useful in case of large data, in another cases it will increase the packet size.ttl
UInt No Specify for how many hours published message
should be stored.payloads
[String : Any] No Dictionary with payloads
for different vendors (Apple withaps
key and Google withgcm
). Eitherpayloads
ormessage
should be provided.metadata
[String : Any] No Dictionary
with values which should be used byPubNub
service to filter messages.block
PNPublishCompletionBlock No The completion block
which will be called when the processing is complete, has one argument: -request
status reports the publish was successful or not (errorData
contains error information in case of failure).
Basic Usage
self.client.fire().channel("my_channel").message("Hello from the PubNub Swift SDK").compress(false).ttl(16).performWithCompletion({ (status) in
if !status.isError {
// Message successfully published to specified channel.
}
else{
/**
Handle message publish 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()
*/
}
});
Signal
Description
The signal()
function is used to send a signal to all subscribers of a channel.
By default, signals are limited to a message payload size of 64
bytes. This limit applies only to the payload, and not to the URI or headers. If you require a larger payload size, please contact support.
Method(s)
To Signal a message
you can use the following method(s) in the Swift SDK:
open func signal(_ message: Any, channel: String, withCompletion: PNSignalCompletionBlock?)
Parameter Type Required Description message
Any Yes Object ( String
,Number
,Array
,Dictionary
) which will be sent with signal.channel
String Yes Name of the channel
to whichsignal
should be sent.closure
PNSignalCompletionBlock No Signal processing completion closure
which pass only one argument - request processing status to report about how data pushing was successful or not.
Basic Usage
Signal a message to a channel:
self.client.signal(["Hello": "world"], channel: "announcement", withCompletion: { status in
if !status.isError {
// Signal successfully sent to specified channel.
} else {
/**
* Handle signal sending error. Check 'category' property to find out possible issue
* because of which request did fail.
*
* Request can be resent using: status.retry();
*/
}
})
Response
Response objects returned by the client when Signal API is used:
open class PNSignalStatusData : PNServiceData {
open var timetoken: NSNumber { get }
open var information: String { get }
}
open class PNSignalStatus : PNAcknowledgmentStatus {
open var data: PNSignalStatusData { get }
}
Signal (Builder Pattern)
Description
Note
This method uses the builder pattern, you can remove the args which are optional.
Method(s)
To run Signal Builder
you can use the following method(s) in the Swift SDK:
signal().message(id).channel(NSString *).performWithCompletion(PNSignalCompletionBlock)
Parameter Type Required Description message
Any Yes Object ( String
,Number
,Array
,Dictionary
) which will be sent with signal.channel
String Yes Name of the channel
to whichsignal
should be sent.closure
PNSignalCompletionBlock No Signal processing completion closure
which pass only one argument - request processing status to report about how data pushing was successful or not.
Basic Usage
Signal a message to a channel:
self.client.signal().message(["Hello": "world"]).channel("announcement")
.performWithCompletion({ status in
if !status.isError {
// Signal successfully sent to specified channel.
} else {
/**
* Handle signal sending error. Check 'category' property to find out possible issue
* because of which request did fail.
*
* Request can be resent using: status.retry();
*/
}
})
Response:
Response objects which is returned by client when Signal API is used::
open class PNSignalStatusData : PNServiceData {
open var timetoken: NSNumber { get }
open var information: String { get }
}
open class PNSignalStatus : PNAcknowledgmentStatus {
open var data: PNSignalStatusData { get }
}
Subscribe
Description
This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified channel
. To subscribe to a channel
the client must send the appropriate subscribeKey
at initialization. By default a newly subscribed client will only receive messages published to the channel after the subscribeToChannels()
call completes.
Tip
You can be notified of connectivity via the connect
callback. By waiting for the connect callback to return before attempting to publish, you can avoid a potential race condition on clients that subscribe and immediately publish messages before the subscribe has completed.
Using Swift SDK, if a client becomes disconnected from a channel, it can automatically attempt to reconnect to that channel and retrieve any available messages that were missed during that period by setting restore
to true
. By default a client will attempt to reconnect after exceeding a 320
second connection timeout.
Warning
Unsubscribing from all channels, and then subscribing to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received timetoken
and thus, there could be some gaps in the subscription that may lead to message loss.
Method(s)
To Subscribe to a channel
you can use the following method(s) in the Swift SDK:
open func subscribeToChannels(_ channels: [String], withPresence shouldObservePresence: Bool)
Parameter Type Required Description channels
[String] Yes List of channel names on which client should try to subscribe. shouldObservePresence
Bool Yes If true presence observation will be enabled for channels
.open func subscribeToChannels(_ channels: [String], withPresence shouldObservePresence: Bool, clientState state: [String : Any]?)
Parameter Type Required Description channels
[String] Yes List of channel names on which client should try to subscribe. shouldObservePresence
Bool Yes If true presence observation will be enabled for channels
.state
[String : Any] No Dictionary object containing the state for the channel. open func subscribeToChannels(_ channels: [String], withPresence shouldObservePresence: Bool, usingTimeToken timeToken: NSNumber?)
Parameter Type Required Description channels
[String] Yes List of channel names on which client should try to subscribe. shouldObservePresence
Bool Yes If true presence observation will be enabled for channels
.timeToken
NSNumber No Specifies time from which to start returning any available cached messages. Message
retrieval withtimetoken
is not guaranteed and should only be considered a best-effort service.open func subscribeToChannels(_ channels: [String], withPresence shouldObservePresence: Bool, usingTimeToken timeToken: NSNumber?, clientState state: [String : Any]?)
Parameter Type Required Description channels
[String] Yes List of channel names on which client should try to subscribe. shouldObservePresence
Bool Yes If true presence observation will be enabled for channels
.timeToken
NSNumber No Specifies time from which to start returning any available cached messages. Message
retrieval withtimetoken
is not guaranteed and should only be considered a best-effort service.state
[String : Any] No Dictionary object containing the state for the channel.
Basic Usage
Subscribe to a channel:
/**
Subscription results arrive to a listener which should implement the PNObjectEventListener protocol and be registered as follows:
*/
self.client.addListener(self)
self.client.subscribeToChannels(["my_channel1","my_channel2"], withPresence: false)
// Handle a new message from a subscribed channel
func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) {
// Reference to the channel group containing the chat the message was sent to
let subscription = message.data.subscription
print("\(message.data.publisher) sent message to '\(message.data.channel)' at
\(message.data.timetoken): \(message.data.message)")
}
// Handle a subscription status change
func client(_ client: PubNub, didReceive status: PNStatus) {
if status.operation == .subscribeOperation {
// Check to see if the message is about a successful subscription or restore
if status.category == .PNConnectedCategory || status.category == .PNReconnectedCategory {
let subscribeStatus: PNSubscribeStatus = status as! PNSubscribeStatus
if subscribeStatus.category == .PNConnectedCategory {
// For a subscribe, this is expected, and means there are no errors or issues
}
else {
// This usually occurs if there is a transient error. The subscribe fails but
// then reconnects, and there is no longer any issue.
}
}
else if status.category == .PNUnexpectedDisconnectCategory {
// This is usually an issue with the internet connection.
// This is an error: handle appropriately, and retry will be called automatically.
}
// Looks like some kind of issues happened while the client tried to subscribe,
// or disconnected from the network.
else {
let errorStatus: PNErrorStatus = status as! PNErrorStatus
if errorStatus.category == .PNAccessDeniedCategory {
// PAM prohibited this client from subscribing to this channel and channel group.
// This is another explicit error.
}
else {
/**
More errors can be directly specified by creating explicit cases for other categories
of `PNStatusCategory` errors, such as:
- `PNDecryptionErrorCategory`
- `PNMalformedFilterExpressionCategory`
- `PNMalformedResponseCategory`
- `PNTimeoutCategory`
- `PNNetworkIssuesCategory`
*/
}
}
}
else if status.operation == .unsubscribeOperation {
if status.category == .PNDisconnectedCategory {
// This is the expected category for an unsubscribe.
// There were no errors in unsubscribing from everything.
}
}
else if status.operation == .heartbeatOperation {
/**
Heartbeat operations can have errors, so check first for an error.
For more information on how to configure heartbeat notifications through the status
PNObjectEventListener callback, consult http://www.pubnub.com/docs/swift/api-reference/configuration#configuration_basic_usage
*/
if !status.isError { /* Heartbeat operation was successful */ }
else { /* There was an error with the heartbeat operation, handle here */ }
}
}
// Handle a new signal from a subscribed channel
func client(_ client: PubNub, didReceiveSignal signal: PNSignalResult) {
print("\(message.data.publisher) sent signal to '\(message.data.channel)' at
\(message.data.timetoken): \(message.data.message)")
}
// Handle a new user event (update or delete) from a subscribed user channel
func client(_ client: PubNub, didReceiveUserEvent event: PNUserEventResult) {
print("'\(event.data.identifier)' user has been \(event.data.event)'ed at
\(event.data.timestamp)")
}
Response
open class PNSubscriberData : PNServiceData {
// Name of channel for which the subscriber received data.
open var channel: String { get }
// Name of channel or channel group (if not equal to channel name).
open var subscription: String? { get }
// Time at which the event arrived.
open var timetoken: NSNumber { get }
// Stores reference to metadata information passed along with the received event.
open var userMetadata: [String : Any]? { get }
}
open class PNSubscribeStatus : PNErrorStatus {
// Timetoken used to establish the current subscription cycle.
open var currentTimetoken: NSNumber { get }
// Stores reference to previous key used in the subscription cycle to receive
// currentTimetoken along with other events.
open var lastTimeToken: NSNumber { get }
// List of channels to which the client is currently subscribed.
open var subscribedChannels: [String] { get }
// List of channel group names on which client currently subscribed.
open var subscribedChannelGroups: [String] { get }
// Structured PNResult data field information.
open var data: PNSubscriberData { get }
}
// Message arrives to event listeners as model described below
open class PNMessageData : PNSubscriberData {
// Message sender identifier.
open var publisher: String { get }
// Message delivered through the data object live feed.
open var message: Any? { get }
}
open class PNMessageResult : PNResult {
// Stores a reference to the message object from live feed.
open var data: PNMessageData { get }
}
// Signal arrives to event listeners as model described below
open class PNSignalData : PNMessageData {
// Signal sender identifier.
open var publisher: String { get }
// Signal message delivered through the data object live feed.
open var message: Any? { get }
}
open class PNSignalResult : PNResult {
// Stores reference to signal object from live feed.
open var data: PNSignalData { get }
}
// User events arrive to event listeners as model described below
open class PNUserEventData : PNSubscriberData {
// List of user model properties which has been changed.
open var modifiedFields: [String] { get }
// Additional / complex attributes which has been associated with user during user create / update requests.
open var custom: Dictionary? { get }
// User identifier from external service (database, auth service).
open var externalId: String? { get }
// URL at which user's profile available.
open var profileUrl: String? { get }
// Email address which has been associated with user.
open var email: String? { get }
// Name which has been associated with user.
open var name: String? { get }
// User identifier.
open var identifier: String { get }
// Time when user event has been triggered.
open var timestamp: Number { get }
// Name of action for which user event has been sent ('update')
open var event: String { get }
// User data modification date or 'nil' if removed.
open var updated: Date? { get }
}
open class PNUserEventResult : PNResult {
// User event object from live feed.
open var data: PNUserEventData { get }
// Space events arrive to event listeners as model described below
open class PNSpaceEventData : PNSubscriberData {
// List of space model properties which has been changed.
open var modifiedFields: [String] { get }
// Additional / complex attributes which has been associated with space during space create / update requests.
open var custom: Dictionary? { get }
// Additional information about space.
open var information: String? { get }
// Name which has been associated with space.
open var name: String? { get }
// Space identifier.
open var identifier: String { get }
// Time when space event has been triggered.
open var timestamp: Number { get }
// Name of action for which space event has been sent ('update')
open var event: String { get }
// Space data modification date or 'nil' if removed.
open var updated: Date? { get }
}
open class PNSpaceEventResult : PNResult {
// Space event object from live feed.
open var data: PNSpaceEventData { get }
}
// User events arrive to event listeners as model described below
open class PNMembershipEventData : PNSubscriberData {
// Additional information which has been associated with user during space membership create / update requests.
open var custom: Dictionary? { get }
// Membership creation date.
open var created: Date? { get }
// Membership modification date or 'nil' if removed.
open var updated: Date? { get }
// Time when membership event has been triggered.
open var timestamp: Number { get }
// Identifier of space wihthin which user has membership.
open var spaceId: String { get }
// Identifier of user for which membership has been 'created' / 'updated' / 'deleted'.
open var userId: String { get }
// Name of action for which membership event has been sent ('create', 'update' or 'delete').
open var event: String { get }
}
open class PNMembershipEventResult : PNResult {
// Membership event object from live feed.
open var data: PNMembershipEventData { get }
}
// User events arrive to event listeners as model described below
open class PNMembershipEventData : PNSubscriberData {
// Additional information which has been associated with user during space membership create / update requests.
open var custom: Dictionary? { get }
// Membership creation date.
open var created: Date? { get }
// Membership modification date or 'nil' if removed.
open var updated: Date? { get }
// Time when membership event has been triggered.
open var timestamp: Number { get }
// Identifier of space wihthin which user has membership.
open var spaceId: String { get }
// Identifier of user for which membership has been 'created' / 'updated' / 'deleted'.
open var userId: String { get }
// Name of action for which membership event has been sent ('create', 'update' or 'delete').
open var event: String { get }
}
open class PNMembershipEventResult : PNResult {
// Membership event object from live feed.
open var data: PNMembershipEventData { get }
}
// Message action events arrive to event listeners as model described below
open class PNMessageActionData : PNSubscriberData {
// Action for which event has been received.
open var action: PNMessageAction { get }
// Name of action for which message action event has been sent ('added') or ('removed')
open var event: String { get }
}
open class PNUserEventResult : PNResult {
// Message action object from live feed.
open var data: PNMessageActionData { get }
}
Other Examples
- Subscribing to a Presence channel: Requires Presence add-onRequires that the Presence add-on is enabled for your key. See this page on enabling add-on features on your keys:
https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending
-pnpres
to the channel name. For example the channel namedmy_channel
would have the presence channel namedmy_channel-pnpres
./** Subscription process results arrive to listener which should adopt to PNObjectEventListener protocol and registered using: */ self.client.addListener(self) self.client.subscribeToPresenceChannels(["my_channel"]) // New presence event handling. func client(_ client: PubNub, didReceivePresenceEvent event: PNPresenceEventResult) { // Handle presence event event.data.presenceEvent (one of: join, leave, timeout, state-change). if event.data.channel != event.data.subscription { // Presence event has been received on channel group stored in event.data.subscription. } else { // Presence event has been received on channel stored in event.data.channel. } if event.data.presenceEvent != "state-change" { print("\(event.data.presence.uuid) \"\(event.data.presenceEvent)'ed\"\n" + "at: \(event.data.presence.timetoken) on \(event.data.channel) " + "(Occupancy: \(event.data.presence.occupancy))"); } else { print("\(event.data.presence.uuid) changed state at: " + "\(event.data.presence.timetoken) on \(event.data.channel) to:\n" + "\(event.data.presence.state)"); } }
Sample Responses
Join Event
{ "action": "join", "timestamp": 1345546797, "uuid": "175c2c67-b2a9-470d-8f4b-1db94f90e39e", "occupancy": 2 }
Leave Event
{ "action" : "leave", "timestamp" : 1345549797, "uuid" : "175c2c67-b2a9-470d-8f4b-1db94f90e39e", "occupancy" : 1 }
Timeout Event
{ "action": "timeout", "timestamp": 1345549797, "uuid": "76c2c571-9a2b-d074-b4f8-e93e09f49bd", "occupancy": 0 }
Custom Presence Event (State Change)
{ "action": "state-change", "uuid": "76c2c571-9a2b-d074-b4f8-e93e09f49bd", "timestamp": 1345549797, "data": { "isTyping": true } }
Interval Event
{ "action":"interval", "timestamp":1474396578, "occupancy":2 }
When a channel is in interval mode with
presence_deltas
pnconfig
flag enabled, the interval message may also include the following fields which contain an array of changed UUIDs since the last interval message.- joined
- left
- timedout
For example, this interval message indicates there were 2 new UUIDs that joined and 1 timed out UUID since the last interval:
{ "action" : "interval", "occupancy" : <# users in channel>, "timestamp" : <unix timestamp>, "joined" : ["uuid2", "uuid3"], "timedout" : ["uuid1"] }
If the full interval message is greater than
30KB
(since the max publish payload is∼32KB
), none of the extra fields will be present. Instead there will be ahere_now_refresh
boolean field set totrue
. This indicates to the user that they should do ahereNow
request to get the complete list of users present in the channel.{ "action" : "interval", "occupancy" : <# users in channel>, "timestamp" : <unix timestamp>, "here_now_refresh" : true }
- Subscribing with State: Requires Presence add-onRequires that the Presence add-on is enabled for your key. See this page on enabling add-on features on your keys:
https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-Note
Always set the
UUID
to uniquely identify the user or device that connects to PubNub. ThisUUID
should be persisted, and should remain unchanged for the lifetime of the user or the device. If you don't set theUUID
, you won't be able to connect to PubNub.// Initialize and configure PubNub client instance let configuration = PNConfiguration(publishKey: "demo", subscribeKey: "demo") self.client = PubNub.clientWithConfiguration(configuration) self.client.addListener(self) // Subscribe to demo channel with presence observation self.client.subscribeToChannels(["my_channel"], withPresence: true) func client(_ client: PubNub, didReceive status: PNStatus) { if status.category == .PNConnectedCategory { self.client.setState(["Key": "Value"], forUUID: self.client.uuid(), onChannel: "my_channel", withCompletion: { (status) in if !status.isError { // Client state successfully modified on specified channel. } else { /** Handle client state modification error. Check 'category' property to find out possible reasons 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() */ } }) } } // Handle new message from one of channels on which client has been subscribed. func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) { // Handle new message stored in message.data.message if message.data.channel != message.data.subscription { // Message has been received on channel group stored in message.data.subscription. } else { // Message has been received on channel stored in message.data.channel. } print("Received message: \(message.data.message) on channel \(message.data.channel) " + "at \(message.data.timetoken)") }
Subscribe Channel Group
Requires Stream Controller add-on Requires that the Stream Controller add-on is enabled for your key. See this page on enabling add-on features on your keys:
https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-
Description
This functions subscribes to a channel group.
Method(s)
To Subscribe to a Channel Group
you can use the following method(s) in the Swift SDK:
open func subscribeToChannelGroups(_ groups: [String], withPresence shouldObservePresence: Bool)
Parameter Type Required Description groups
[String] Yes List of channel
group names on which client should try tosubscribe
.shouldObservePresence
Bool Yes If true presence observation will be enabled for channels groups
.open func subscribeToChannelGroups(_ groups: [String], withPresence shouldObservePresence: Bool, clientState state: [String : Any]?)
Parameter Type Required Description groups
[String] Yes List of channel
group names on which client should try tosubscribe
.shouldObservePresence
Bool Yes If true presence observation will be enabled for channels groups
.state
[String : Any] No Reference on dictionary which stores key-value pairs based on channel
group name and value which should be assigned to it.
Basic Usage
Subscribe to a channel group
let channelGroup = "family"
/**
Subscription process results arrive to listener which should adopt to PNObjectEventListener protocol
and registered using:
*/
self.client.addListener(self)
self.client.subscribeToChannelGroups([channelGroup], withPresence: false)
// Handle new message from one of channels on which client has been subscribed.
func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) {
// Handle new message stored in message.data.message
if message.data.channel != message.data.subscription {
// Message has been received on channel group stored in message.data.subscription.
}
else {
// Message has been received on channel stored in message.data.channel.
}
print("Received message: \(message.data.message) on channel \(message.data.channel) " +
"at \(message.data.timetoken)")
}
// Handle subscription status change.
func client(_ client: PubNub, didReceive status: PNStatus) {
if status.operation == .subscribeOperation {
// Check whether received information about successful subscription or restore.
if status.category == .PNConnectedCategory || status.category == .PNReconnectedCategory {
let subscribeStatus: PNSubscribeStatus = status as! PNSubscribeStatus
if subscribeStatus.category == .PNConnectedCategory {
// This is expected for a subscribe, this means there is no error or issue whatsoever.
}
else {
/**
This usually occurs if subscribe temporarily fails but reconnects. This means there was
an error but there is no longer any issue.
*/
}
}
else if status.category == .PNUnexpectedDisconnectCategory {
/**
This is usually an issue with the internet connection, this is an error, handle
appropriately retry will be called automatically.
*/
}
// Looks like some kind of issues happened while client tried to subscribe or disconnected from
// network.
else {
let errorStatus: PNErrorStatus = status as! PNErrorStatus
if errorStatus.category == .PNAccessDeniedCategory {
/**
This means that PAM does allow this client to subscribe to this channel and channel group
configuration. This is another explicit error.
*/
}
else {
/**
More errors can be directly specified by creating explicit cases for other error categories
of `PNStatusCategory` such as: `PNDecryptionErrorCategory`,
`PNMalformedFilterExpressionCategory`, `PNMalformedResponseCategory`, `PNTimeoutCategory`
or `PNNetworkIssuesCategory`
*/
}
}
}
}
Response
open class PNSubscriberData : PNServiceData {
// Name of channel for which subscriber received data.
open var channel: String { get }
// Name of channel or channel group (in case if not equal to channel).
open var subscription: String? { get }
// Time at which event arrived.
open var timetoken: NSNumber { get }
// Stores reference on metadata information which has been passed along with received event.
open var userMetadata: [String : Any]? { get }
}
open class PNSubscribeStatus : PNErrorStatus {
// Timetoken which has been used to establish current subscription cycle.
open var currentTimetoken: NSNumber { get }
// Stores reference on previous key which has been used in subscription cycle to receive
// currentTimetoken along with other events.
open var lastTimeToken: NSNumber { get }
// List of channels on which client currently subscribed.
open var subscribedChannels: [String] { get }
// List of channel group names on which client currently subscribed.
open var subscribedChannelGroups: [String] { get }
// Structured PNResult data field information.
open var data: PNSubscriberData { get }
}
// Message arrive to event listeners as model described below
open class PNMessageData : PNSubscriberData {
// Message sender identifier.
open var publisher: String { get }
// Message which has been delivered through data object live feed.
open var message: Any? { get }
}
open class PNMessageResult : PNResult {
// Stores reference on message object from live feed.
open var data: PNMessageData { get }
}
Other Examples
- Subscribe to the presence channel of a channel group: Requires Stream Controller and Presence add-onRequires that both Stream Controller and Presence add-ons are enabled for your key. See this page on enabling add-on features on your keys:
https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-/** Subscription process results arrive to listener which should adopt to PNObjectEventListener protocol and registered using: */ self.client.addListener(self) self.client.subscribeToChannelGroups([channelGroup], withPresence: true) // Handle new message from one of channels on which client has been subscribed. func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) { // Handle new message stored in message.data.message if message.data.channel != message.data.subscription { // Message has been received on channel group stored in message.data.subscription. } else { // Message has been received on channel stored in message.data.channel. } print("Received message: \(message.data.message) on channel \(message.data.channel) " + "at \(message.data.timetoken)") } // New presence event handling. func client(_ client: PubNub, didReceivePresenceEvent event: PNPresenceEventResult) { // Handle presence event event.data.presenceEvent (one of: join, leave, timeout, state-change). if event.data.channel != event.data.subscription { // Presence event has been received on channel group stored in event.data.subscription. } else { // Presence event has been received on channel stored in event.data.channel. } if event.data.presenceEvent != "state-change" { print("\(event.data.presence.uuid) \"\(event.data.presenceEvent)'ed\"\n" + "at: \(event.data.presence.timetoken) on \(event.data.channel) " + "(Occupancy: \(event.data.presence.occupancy))"); } else { print("\(event.data.presence.uuid) changed state at: " + "\(event.data.presence.timetoken) on \(event.data.channel) to:\n" + "\(event.data.presence.state)"); } } // Handle subscription status change. func client(_ client: PubNub, didReceive status: PNStatus) { if status.operation == .subscribeOperation { // Check whether received information about successful subscription or restore. if status.category == .PNConnectedCategory || status.category == .PNReconnectedCategory { let subscribeStatus: PNSubscribeStatus = status as! PNSubscribeStatus if subscribeStatus.category == .PNConnectedCategory { // This is expected for a subscribe, this means there is no error or issue whatsoever. } else { /** This usually occurs if subscribe temporarily fails but reconnects. This means there was an error but there is no longer any issue. */ } } else if status.category == .PNUnexpectedDisconnectCategory { /** This is usually an issue with the internet connection, this is an error, handle appropriately retry will be called automatically. */ } // Looks like some kind of issues happened while client tried to subscribe or disconnected from // network. else { let errorStatus: PNErrorStatus = status as! PNErrorStatus if errorStatus.category == .PNAccessDeniedCategory { /** This means that PAM does allow this client to subscribe to this channel and channel group configuration. This is another explicit error. */ } else { /** More errors can be directly specified by creating explicit cases for other error categories of `PNStatusCategory` such as: `PNDecryptionErrorCategory`, `PNMalformedFilterExpressionCategory`, `PNMalformedResponseCategory`, `PNTimeoutCategory` or `PNNetworkIssuesCategory` */ } } } }
Unsubscribe
Description
When subscribed to a single channel, this function causes the client to issue a leave
from the channel
and close any open socket to the PubNub Network. For multiplexed channels, the specified channel
(s) will be removed and the socket remains open until there are no more channels remaining in the list.
Warning
Unsubscribing from all channels, and then subscribing to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received timetoken
and thus, there could be some gaps in the subscription that may lead to message loss.
Method(s)
To Unsubscribe from a channel
you can use the following method(s) in the Swift SDK:
open func unsubscribeFromChannels(_ channels: [String], withPresence shouldObservePresence: Bool)
Parameter Type Required Description group
[String] Yes List of channel group names from which client should try to unsubscribe. shouldObservePresence
Bool Yes If true the presence observation will also be unsubscribed on specified channels.
Basic Usage
Unsubscribe from a channel:
/**
Subscription process results arrive to listener which should adopt to
PNObjectEventListener protocol and registered using:
*/
self.client.addListener(self)
self.client.unsubscribeFromChannels(["my_channel1", "my_channel2"], withPresence: false)
// Handle subscription status change.
func client(_ client: PubNub, didReceive status: PNStatus) {
if status.operation == .unsubscribeOperation && status.category == .PNDisconnectedCategory {
/**
This is the expected category for an unsubscribe. This means there was no error in
unsubscribing from everything.
*/
}
}
Response
open class PNSubscriberData : PNServiceData {
// Name of channel for which subscriber received data.
open var channel: String { get }
// Name of channel or channel group (in case if not equal to channel).
open var subscription: String? { get }
// Time at which event arrived.
open var timetoken: NSNumber { get }
// Stores reference on metadata information which has been passed along with received event.
open var userMetadata: [String : Any]? { get }
}
open class PNSubscribeStatus : PNErrorStatus {
// Timetoken which has been used to establish current subscription cycle.
open var currentTimetoken: NSNumber { get }
// Stores reference on previous key which has been used in subscription cycle to receive
// currentTimetoken along with other events.
open var lastTimeToken: NSNumber { get }
// List of channels on which client currently subscribed.
open var subscribedChannels: [String] { get }
// List of channel group names on which client currently subscribed.
open var subscribedChannelGroups: [String] { get }
// Structured PNResult data field information.
open var data: PNSubscriberData { get }
}
Unsubscribe All
Description
Unsubscribe from all channels and all channel groups
Method(s)
open func unsubscribeFromAll()
Basic Usage
/**
Subscription process results arrive to listener which should adopt to
PNObjectEventListener protocol and registered using:
*/
self.client?.addListener(self)
self.client?.unsubscribeFromAll()
// Handle subscription status change.
func client(client: PubNub, didReceiveStatus status: PNStatus) {
if status.operation == .unsubscribeOperation && status.category == .PNDisconnectedCategory {
/**
This is the expected category for an unsubscribe. This means there was no error in
unsubscribing from everything.
*/
}
}
Returns
None
Unsubscribe from a Channel Group
Description
This function lets you Unsubscribe from a Channel Group
Method(s)
To run Unsubscribe from a Channel Group
you can use the following method(s) in the Swift SDK:
open func unsubscribeFromChannelGroups(_ groups: [String], withPresence shouldObservePresence: Bool)
Parameter Type Required Description group
[String] Yes List of channel group names from which client should try to unsubscribe. shouldObservePresence
Bool Yes Whether client should disable presence observation on specified channel
groups or keep listening for presence event on them.
Basic Usage
Unsubscribe from a Channel Group:
/**
Unsubscription process results arrive to listener which should adopt to
PNObjectEventListener protocol and registered using:
*/
self.client.addListener(self)
self.client.unsubscribeFromChannelGroups(["developers"], withPresence: true)
// Handle subscription status change.
func client(client: PubNub, didReceiveStatus status: PNStatus) {
if status.operation == .unsubscribeOperation && status.category == .PNDisconnectedCategory {
/**
This is the expected category for an unsubscribe. This means there was no error in
unsubscribing from everything.
*/
}
}
Response
open class PNSubscriberData : PNServiceData {
// Name of channel for which subscriber received data.
open var channel: String { get }
// Name of channel or channel group (in case if not equal to channel).
open var subscription: String? { get }
// Time at which event arrived.
open var timetoken: NSNumber { get }
// Stores reference on metadata information which has been passed along with received event.
open var userMetadata: [String : Any]? { get }
}
open class PNSubscribeStatus : PNErrorStatus {
// Timetoken which has been used to establish current subscription cycle.
open var currentTimetoken: NSNumber { get }
// Stores reference on previous key which has been used in subscription cycle to receive
// currentTimetoken along with other events.
open var lastTimeToken: NSNumber { get }
// List of channels on which client currently subscribed.
open var subscribedChannels: [String] { get }
// List of channel group names on which client currently subscribed.
open var subscribedChannelGroups: [String] { get }
// Structured PNResult data field information.
open var data: PNSubscriberData { get }
}
Presence
Description
This function is used to subscribe to the presence channel. Using Swift SDK, if a client becomes disconnected from a channel, it can automatically attempt to reconnect to that channel and retrieve any available messages that were missed during that period by setting restore
to true
. By default a client will attempt to reconnect after exceeding a 320
second connection timeout.
Method(s)
To do Presence
you can use the following method(s) in the Swift SDK:
open func subscribeToPresenceChannels(_ channels: [String])
Parameter Type Required Description channels
[String] Yes Specifies the channel(s)
to subscribe to presence channel. It is possible to specify multiple channels.
Basic Usage
Subscribe to the presence channel: For any given channel there is an associated Presence
channel. You can subscribe directly to the channel by appending -pnpres
to the channel name. For example the channel named my_channel
would have the presence channel named my_channel-pnpres
/**
Subscription process results arrive to listener which should adopt to
PNObjectEventListener protocol and registered using:
*/
self.client.addListener(self)
self.client.subscribeToPresenceChannels(["my_channel"])
// New presence event handling.
func client(_ client: PubNub, didReceivePresenceEvent event: PNPresenceEventResult) {
// Handle presence event event.data.presenceEvent (one of: join, leave, timeout, state-change).
if event.data.channel != event.data.subscription {
// Presence event has been received on channel group stored in event.data.subscription.
}
else {
// Presence event has been received on channel stored in event.data.channel.
}
if event.data.presenceEvent != "state-change" {
print("\(event.data.presence.uuid) \"\(event.data.presenceEvent)'ed\"\n" +
"at: \(event.data.presence.timetoken) on \(event.data.channel) " +
"(Occupancy: \(event.data.presence.occupancy))");
}
else {
print("\(event.data.presence.uuid) changed state at: " +
"\(event.data.presence.timetoken) on \(event.data.channel) to:\n" +
"\(event.data.presence.state)");
}
}
Response
open class PNSubscriberData : PNServiceData {
// Name of channel for which subscriber received data.
open var channel: String { get }
// Name of channel or channel group (in case if not equal to channel).
open var subscription: String? { get }
// Time at which event arrived.
open var timetoken: NSNumber { get }
// Stores reference on metadata information which has been passed along with received event.
open var userMetadata: [String : Any]? { get }
}
open class PNSubscribeStatus : PNErrorStatus {
// Timetoken which has been used to establish current subscription cycle.
open var currentTimetoken: NSNumber { get }
// Stores reference on previous key which has been used in subscription cycle to receive
// currentTimetoken along with other events.
open var lastTimeToken: NSNumber { get }
// List of channels on which client currently subscribed.
open var subscribedChannels: [String] { get }
// List of channel group names on which client currently subscribed.
open var subscribedChannelGroups: [String] { get }
// Structured PNResult data field information.
open var data: PNSubscriberData { get }
}
// Presence events arrive to event listeners as model described below
open class PNPresenceDetailsData : PNSubscriberData {
// Time when presence event has been triggered.
open var timetoken: NSNumber { get }
// Reference on unique user identifier for which event has been triggered.
open var uuid: String? { get }
// List of newly joined subscribers' UUID.
open var join: [String]? { get }
// List of recently leaved subscribers' UUID.
open var leave: [String]? { get }
// List of recently UUID of subscribers which leaved by timeout.
open var timeout: [String]? { get }
// Channel presence information.
open var occupancy: NSNumber { get }
// User changed client state.
open var state: [String : Any]? { get }
}
open class PNPresenceEventData : PNSubscriberData {
// Type of presence event.
open var presenceEvent: String { get }
// Additional presence information.
open var presence: PNPresenceDetailsData { get }
}
open class PNPresenceEventResult : PNResult {
// Stores reference on presence event object from live feed.
open var data: PNPresenceEventData { get }
}
Presence Unsubscribe
Description
This function lets you stop monitoring the presence of the channel
(s). The channel(s) will be removed and the socket remains open until there are no more channels remaining in the list.
Method(s)
To Unsubscribe from Presence of a channel
you can use the following method(s) in the Swift SDK:
open func unsubscribeFromPresenceChannels(_ channels: [String])
Parameter Type Required Description channels
[String] Yes List of channel
names for which client should try tounsubscribe
from presence observingchannels
Basic Usage
Unsubscribe from the presence channel:
// Unsubscribe from one of channels presence channels.
self.client.unsubscribeFromPresenceChannels(["my_channel"])
Response
open class PNSubscriberData : PNServiceData {
// Name of channel for which subscriber received data.
open var channel: String { get }
// Name of channel or channel group (in case if not equal to channel).
open var subscription: String? { get }
// Time at which event arrived.
open var timetoken: NSNumber { get }
// Stores reference on metadata information which has been passed along with received event.
open var userMetadata: [String : Any]? { get }
}
open class PNSubscribeStatus : PNErrorStatus {
// Timetoken which has been used to establish current subscription cycle.
open var currentTimetoken: NSNumber { get }
// Stores reference on previous key which has been used in subscription cycle to receive
// currentTimetoken along with other events.
open var lastTimeToken: NSNumber { get }
// List of channels on which client currently subscribed.
open var subscribedChannels: [String] { get }
// List of channel group names on which client currently subscribed.
open var subscribedChannelGroups: [String] { get }
// Structured PNResult data field information.
open var data: PNSubscriberData { get }
}
Listeners
Description
You can be notified of connectivity status, message and presence notifications via the listeners.
Listeners should be added before calling the method.
Adding Listeners
/**
Subscription results arrive to a listener which should implement the PNObjectEventListener protocol and be registered as follows:
*/
self.client.addListener(self)
self.client.subscribeToChannels(["my_channel1","my_channel2"], withPresence: false)
// Handle a new message from a subscribed channel
func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) {
// Reference to the channel group containing the chat the message was sent to
let subscription = message.data.subscription
print("\(message.data.publisher) sent message to '\(message.data.channel)' at
\(message.data.timetoken): \(message.data.message)")
}
// Handle a subscription status change
func client(_ client: PubNub, didReceive status: PNStatus) {
if status.operation == .subscribeOperation {
// Check to see if the message is about a successful subscription or restore
if status.category == .PNConnectedCategory || status.category == .PNReconnectedCategory {
let subscribeStatus: PNSubscribeStatus = status as! PNSubscribeStatus
if subscribeStatus.category == .PNConnectedCategory {
// For a subscribe, this is expected, and means there are no errors or issues
}
else {
// This usually occurs if there is a transient error. The subscribe fails but
// then reconnects, and there is no longer any issue.
}
}
else if status.category == .PNUnexpectedDisconnectCategory {
// This is usually an issue with the internet connection.
// This is an error: handle appropriately, and retry will be called automatically.
}
// Looks like some kind of issues happened while the client tried to subscribe,
// or disconnected from the network.
else {
let errorStatus: PNErrorStatus = status as! PNErrorStatus
if errorStatus.category == .PNAccessDeniedCategory {
// PAM prohibited this client from subscribing to this channel and channel group.
// This is another explicit error.
}
else {
/**
More errors can be directly specified by creating explicit cases for other categories
of `PNStatusCategory` errors, such as:
- `PNDecryptionErrorCategory`
- `PNMalformedFilterExpressionCategory`
- `PNMalformedResponseCategory`
- `PNTimeoutCategory`
- `PNNetworkIssuesCategory`
*/
}
}
}
else if status.operation == .unsubscribeOperation {
if status.category == .PNDisconnectedCategory {
// This is the expected category for an unsubscribe.
// There were no errors in unsubscribing from everything.
}
}
else if status.operation == .heartbeatOperation {
/**
Heartbeat operations can have errors, so check first for an error.
For more information on how to configure heartbeat notifications through the status
PNObjectEventListener callback, consult http://www.pubnub.com/docs/swift/api-reference/configuration#configuration_basic_usage
*/
if !status.isError { /* Heartbeat operation was successful */ }
else { /* There was an error with the heartbeat operation, handle here */ }
}
}
// Handle a new presence event
func client(_ client: PubNub, didReceivePresenceEvent event: PNPresenceEventResult) {
// Handle presence event event.data.presenceEvent (one of: join, leave, timeout, state-change).
if event.data.channel != event.data.subscription {
// Presence event received on a channel group stored in event.data.subscription
}
else {
// Presence event received on a channel stored in event.data.channel
}
if event.data.presenceEvent != "state-change" {
print("\(event.data.presence.uuid) \"\(event.data.presenceEvent)'ed\"\n" +
"at: \(event.data.presence.timetoken) on \(event.data.channel) " +
"(Occupancy: \(event.data.presence.occupancy))");
}
else {
print("\(event.data.presence.uuid) changed state at: " +
"\(event.data.presence.timetoken) on \(event.data.channel) to:\n" +
"\(event.data.presence.state)");
}
}
// Handle a new signal from a subscribed channel
func client(_ client: PubNub, didReceiveSignal signal: PNSignalResult) {
print("\(message.data.publisher) sent signal to '\(message.data.channel)' at
\(message.data.timetoken): \(message.data.message)")
}
// Handle a new user event (update or delete) from a subscribed user channel
func client(_ client: PubNub, didReceiveUserEvent event: PNUserEventResult) {
print("'\(event.data.identifier)' user has been \(event.data.event)'ed at
\(event.data.timestamp)")
}
// Handle a new space event (update or delete) from a subscribed space channel
func client(_ client: PubNub, didReceiveSpaceEvent event: PNSpaceEventResult) {
print("'\(event.data.identifier)' space has been \(event.data.event)'ed at
\(event.data.timestamp)")
}
// Handle a new membership event from a subscribed user or space channel
func client(_ client: PubNub, didReceiveMembershipEvent event: PNMembershipEventResult) {
print("Membership between '\(event.data.userId)' user '\(event.data.spaceId)' space has been
\(event.data.event)'ed at \(event.data.timestamp)")
}
// Handle message actions (added or removed) from one of channels on which client has been subscribed.
func client(_ client: PubNub, didReceiveMessageAction action: PNUserEventResult) {
print("'\(action.type)' action with '\(action.value)' value has been \(event.data.event) by \(action.uuid) at
\(action.actionTimetoken) to message with \(action.messageTimetoken) timetoken")
}
Listener status events
This is the list of categories which can be received by an event listener:
Category | Description |
---|---|
PNAccessDeniedCategory | Subscribe request failed because of access error (active PAM). status.errorData.channels or status.errorData.channelGroups contain list of channels and/or groups to which user with specified auth key doesn't have access. |
PNDecryptionErrorCategory | Subscribe request returned messages which can't be decrypted with configured cipherKey . Unencrypted message will be returned in status.associatedObject where associatedObject is PNMessageData which contain channel and message properties. |
PNNetworkIssuesCategory | Subscribe request failed because there was no network connection at the moment when request has been sent. |
PNConnectedCategory | Subscribe request successfully completed and client connected to real-time data channels. |
PNReconnectedCategory | Subscribe request successfully completed and client has been reconnected to real-time data channels after unexpected disconnection (PNUnexpectedDisconnectCategory ). |
PNDisconnectedCategory | Client did unsubscribe from specified real-time data channels. |
PNUnexpectedDisconnectCategory | Previously started subscribe loop did fail and at this moment client disconnected from real-time data channels. |
PNRequestMessageCountExceededCategory | If requestMessageCountThreshold is set, this status event will arrive each time when client receive more messages when it has been specified for PNConfiguration property. |
PNMalformedFilterExpressionCategory | Subscription request can't be processed by PubNub service because filter expression malformed and can't be evaluated. |
PNHeartbeatOperation | In case if presence heartbeat value is set, client will sent this status category at specified periods. If status.isError set to YES it mean what heartbeat request did fail (potentially because of network issues). |
This is list of categories which can be received in API completion blocks (non-subscribe):
Category | Description |
---|---|
PNAcknowledgmentCategory | Used API report success with this status category. |
PNAccessDeniedCategory | Request failed because of access error (active PAM). status.errorData.channels or status.errorData.channelGroups contain list of channels and/or groups to which user with specified auth key doesn't have access. |
PNTimeoutCategory | Used API didn't received response from server in time. |
PNNetworkIssuesCategory | API did fail because there was no network connection at the moment when request has been sent. |
PNMalformedResponseCategory | Request received in response non-JSON data. It can be because of publish WiFi hotspot which require authorization or proxy server message. |
PNBadRequestCategory | Request can't be completed because not all required values has been passed or passed values has unexpected data type. |
PNDecryptionErrorCategory | History API may return this status category in case if some messages can't be decrypted. Unencrypted message will be returned in status.associatedObject where associatedObject is PNMessageData which contain channel and message properties. |
PNTLSConnectionFailedCategory | TLS handshake issues and in most cases because of poor connection quality and packets loss and delays. |
PNTLSUntrustedCertificateCategory | Origin to which client tried to connect has untrusted certificate. |