- Description
- Requirements
- Installation -Manual -CocoaPods
- Usage
- PubSub Tests
- Author
- License
The Swift client SDK containing the Cogs Pub Sub API.
- iOS 9.0+
- Xcode 8.0+
- Swift 3.0+
- Check out or download CogsSDK.
- Open CogsSDK.xcworkspace in Xcode.
- Build.
- Navigate to the derived data folder and copy CogsSDK.framework and add it to you project.
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods
To integrate CogsSDK into your Xcode project using CocoaPods, specify it in your Podfile
:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
target '<Your Target Name>' do
pod 'CogsSDK'
end
Then, run the following command:
$ pod install
Create a PubSubOptions
and set connection's options and event handlers. If no options are provided the default ones would be set.
let options = PubSubOptions.defaultOptions
or
let options = PubSubOptions(url: url,
connectionTimeout: 30,
autoReconnect: true,
minReconnectDelay: 5,
maxReconnectDelay: 300,
maxReconnectAttempts: -1,
onNewSessionHandler: { (sessionUUID) in
print(sessionUUID)
},
onReconnectHandler: {
print("Session is restored")
},
onRawRecordHandler: { (record) in
print (record)
},
onMessageHandler: { (receivedMessage) in
print (receivedMessage)
},
onCloseHandler: { (error) in
if let err = error {
print(err.localizedDescription)
} else {
print("Session is closed")
}
},
onErrorHandler: { (error) in
print(error.localizedDescription)
},
onErrorResponseHandler: { (responseError) in
print("\(responseError.message) \n \(responseError.code)")
})
The onNewSession
event indicates that the session associated with this connection is not a resumed session, therefore there are no subscriptions associated with this session. If there had been a previous session and the connection was replaced by an auto-reconnect, the previous session was not restored resulting in all subscriptions being lost.
options.onNewSession = { sessionUUID in
print("New session \(sessionUUID) is opened."
}
The onReconnect
event is emitted on socket reconnection if it disconnected for any reason.
options.onReconnect = {
print("Session is restored")
}
The onRawRecord
event is emitted for every raw record received from the server, whether a response to a request or a message. This is mostly useful for debugging issues with server communication.
options.onRawRecord = { (record) in
print (record)
}
The onMessage
event is emitted whenever the socket receives messages from any channel.
options.onMessage = { (receivedMessage) in
print (receivedMessage)
}
The onError
event is emitted on any connection errors, failed publishes, or when any exception is thrown.
options.onError = { (error) in
print(error.localizedDescription)
}
The onErrorResponse
event is emitted whenever a message is sent to the user with an error status code.
options.onErrorResponse = { (responseError) in
print("\(responseError.message) \n \(responseError.code)")
}
The onClose
event is emitted whenever the socket connection closes.
options.onClose = { (error) in
if let err = error {
print(err.localizedDescription)
} else {
print("Session is closed")
}
}
Create a PubSubService
object to obtain a connection handle. The created PubSubConnectionHandle
object initializes and establishes a web socket connection.
let keys: [String] = ["read key", "write key", "admin key"]
let options = PubSubOptions(url: url,
connectionTimeout: 30,
autoReconnect: true,
minReconnectDelay: 5,
maxReconnectDelay: 300,
maxReconnectAttempts: -1,
onNewSessionHandler: { (sessionUUID) in
print(sessionUUID)
},
onReconnectHandler: {
print("Session is restored")
},
onRawRecordHandler: { (record) in
print (record)
},
onMessageHandler: { (receivedMessage) in
print (receivedMessage)
},
onCloseHandler: { (error) in
if let err = error {
print(err.localizedDescription)
} else {
print("Session is closed")
}
},
onErrorHandler: { (error) in
print(error.localizedDescription)
},
onErrorResponseHandler: { (responseError) in
print("\(responseError.message) \n \(responseError.code)")
})
let connection = PubSubService.connnect(keys: keys,
options: options)
This is a summary of all functions exposed by the PubSubConnectionHandle
object, and examples of their usage.
Fetch the session UUID from the server. The successful result contains the UUID associated with this connection's session.
connection.getSessionUuid { outcome in
switch outcome {
case .pubSubSuccess(let uuid):
print("Session uuid \(uuid)")
case .pubSubResponseError(let error):
print(error)
}
}
Subscribes the connection to a channel, supplying a handler which will be called with each message received from this channel. The successful result contains a list of the subscribed channels.The connection needs read permissions in order to subscribe to a channel.
connection.subscribe(channel: channel,
messageHandler: { (message) in
print("\(message.id) | \(message.message)")
}) { outcome in
switch outcome {
case .pubSubSuccess(let subscribedChannels):
print(subscribedChannels)
case .pubSubResponseError(let error):
print(error)
}
}
Unsubscribes the connection from a particular channel. The successful result contains an array with currently subscribed channels without the channel just unsubscribed from. The connection needs read permission in order to unsubscribe from the channel.
connection.unsubscribe(channel: channel){ outcome in
switch outcome {
case .pubSubSuccess(let subscribedChannels):
print(subscribedChannels) //The list won't include the channel to unsubscribe from
case .pubSubResponseError(let error):
print(error)
}
}
Unsubscribes connection from all channels. The successful result should be an empty array. The connection needs read permission in order to unsubscribe from all channels.
connection.unsubscribeAll(){ outcome in
switch outcome {
case .pubSubSuccess(let subscribedChannels):
print(subscribedChannels)
// This is the list of channels to which we were subscribed prior to running this operation.
case .pubSubResponseError(let error):
print(error)
}
}
Gets all subscriptions. The successful result contains an array with currently subscribed channels.
connection.listSubscriptions(){ outcome in
switch outcome {
case .pubSubSuccess(let subscribedChannels):
print(subscribedChannels)
case .pubSubResponseError(let error):
print(error)
}
}
Publishes a message to a channel. The connection must have write permissions to successfully publish a message. The message string is limited to 64KiB. Messages that exceed this limit will result in the termination of the websocket connection.
connection.publish(channel: channel, message: messageText){ error in
print(error as Any)
}
Publishes a message to a channel. The successful result contains the UUID of the published message.
connection.publishWithAck(channel: channel, message: messageText){ outcome in
switch outcome {
case .pubSubSuccess(let messadeUuid):
print(messadeUuid)
case .pubSubResponseError(let error):
print(error)
}
}
Drops connection.
connection.dropConnection()
Closes the pub/sub connection handle by closing the WebSocket.
connection.close()
There is no service to setup as the CogsSDK maintains a singleton instance of the service internally. You need to make sure your client auth components (access-key, client-salt, and client-secret) are available for each of your requests.
import CogsSDK
// Hex encoded access-key from one of your api keys in the Web UI.
let accessKey: String = "0000"
// Hex encoded client salt/secret pair acquired from /client_secret endpoint and
// associated with above access-key.
let clientSalt: String = "0000"
let clientSecret: String = "0000"
// Acquire the CogsSDK service singleton
cogsService = GambitService.sharedGambitService
This API route is used send an event to Cogs.
// This will be sent along with messages so that you can identify the event which
// "triggered" the message delivery.
let eventName: String = "my-event"
// The name of the namespace for which the event is destined.
let namespace: String = "my-namespace"
// The event attributes whose names and types should match the namespace schema.
let attributes: [String: AnyObject] = [
"uuid": "deadbeef-dead-beef-dead-beefdeadbeef"
]
// Assemble the event
let eventRequeset = GambitRequestEvent(
accessKey: accessKey,
clientSalt: clientSalt,
clientSecret: clientSecret,
eventName: eventName,
namespace: namespace,
attributes: attributes
)
// Send the event, and handle the response
cogsService.requestEvent(eventRequeset) { dat, rsp, err in
if let error = err {
// Handle error
}
else if let response = rsp as? NSHTTPURLResponse {
if response.statusCode == 200 {
if let data = dat {
do {
let json : JSON = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
let parsedResponse = try GambitResponseEvent(json: json)
// Handle message content
} catch {
// Handle JSON parse error
}
} else {
// Handle no response data
}
} else {
// Handle non-200 status code
}
}
}
This API route is used to register a device to receive push notifications for a particular topic within a namespace.
// The iOS app identifier.
let platformAppId: String = "com.example.app"
// The app environment.
let environment: String = "production"
// The unique identifier for the device used to deliver APNS notifications.
let udid: String = "0000"
// The name of the namespace to which the device is registering for notifications
// on the specified topic.
let namespace: String = "my-namespace"
// The primary key attributes which identify the topic, whose names and types
// must match the namespace schema.
let pkAttributes: [String: AnyObject] = [
"uuid": "deadbeef-dead-beef-dead-beefdeadbeef"
]
let pushRequest = GambitRequestPush(
clientSalt: clientSalt,
clientSecret: clientSecret,
UDID: udid,
accessKey: accessKey,
attributes: pkAttributes,
environment: environment,
platformAppID: platformAppId,
namespace: namespace
)
// Send the push registration, and handle the response.
cogsService.registerPush(pushRequest) { dat, rsp, err in
if let error = err {
// Handle error
}
else if let response = rsp as? NSHTTPURLResponse {
if response.statusCode == 200 {
if let data = dat {
do {
let json : JSON = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
let parsedResponse = try GambitResponsePush(json: json)
// Handle message content
} catch {
// Handle JSON parse error
}
} else {
// Handle no response data
}
} else {
// Handle non-200 status code
}
}
}
This API route is used to unregister a device from a particular namespace/topic pair to which it was previously registered for push notifications.
// The iOS app identifier.
let platformAppId: String = "com.example.app"
// The app environment.
let environment: String = "production"
// The unique identifier for the device used to deliver APNS notifications.
let udid: String = "0000"
// The name of the namespace from which the device is unregistering for
// notifications on the specified topic.
let namespace: String = "my-namespace"
// The primary key attributes which identify the topic, whose names and types
// must match the namespace schema.
let pkAttributes: [String: AnyObject] = [
"uuid": "deadbeef-dead-beef-dead-beefdeadbeef"
]
// Assemble the push de-registration request
let pushRequest = GambitRequestPush(
clientSalt: clientSalt,
clientSecret: clientSecret,
UDID: udid,
accessKey: accessKey,
attributes: pkAttributes,
environment: environment,
platformAppID: platformAppId,
namespace: namespace
)
// Send the push de-registration, and handle the response.
cogsService.unregisterPush(pushRequest) { dat, rsp, err in
if let error = err {
// Handle error
}
else if let response = rsp as? NSHTTPURLResponse {
if response.statusCode == 200 {
if let data = dat {
do {
let json : JSON = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
let parsedResponse = try GambitResponsePush(json: json)
// Handle message content
} catch {
// Handle JSON parse error
}
} else {
// Handle no response data
}
} else {
// Handle non-200 status code
}
}
}
This API route is used to fetch the full content of a message by its ID. This is necessary since push notifications don't deliver the entire message content, only the message's ID.
// The ID of the message to be fetched.
let messageId: String = "00000000-0000-0000-0000-000000000000"
// The namespace of the message to be fetched.
let namespace: String = "my-namespace"
// The attributes identifying the topic of the message.
let pkAttributes: [String: AnyObject] = [
"uuid": "deadbeef-dead-beef-dead-beefdeadbeef"
]
// Assemble the message request.
let messageRequest = GambitRequestPush(
accessKey: accessKey,
clientSalt: clientSalt,
clientSecret: clientSecret,
token: messageId,
namespace: namespace,
attributes: pkAttributes
)
// Send request the message, and handle the response.
cogsService.message(messageRequest) { dat, rsp, err in
if let error = err {
// Handle error
}
else if let response = rsp as? NSHTTPURLResponse {
if response.statusCode == 200 {
if let data = dat {
do {
let json : JSON = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
let parsedResponse = try GambitResponseMessage(json: json)
// Handle message content
} catch {
// Handle JSON parse error
}
} else {
// Handle no response data
}
} else {
// Handle non-200 status code
}
}
}
- Locate the
Keys.plist
file from theTests
folder in the project pane in Xcode and populateadminKey
,readKey
andwriteKey
with your own keys - Go to the Test navigator in Xcode (the rhombus icon among the buttons on the top)
- Expand
CogsSDK_Tests
and select test class or single test to run - Click on the play button to the right
Aviata Inc.
Copyright 2016 Aviata Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.