Create an OS X®/macOS® client that publishes data through topics
on
Diffusion™
Cloud
.
To complete this example, you need Apple's Xcode installed on your
development system and a
Diffusion
Cloud service. For more information
about getting a
Diffusion
Cloud service, see Getting started with Diffusion Cloud.
You also require a named user that has a role with the modify_topic and update_topic
permissions. For example, the "TOPIC_CONTROL" role. For more information about roles
and permissions, see Role-based authorization.
This example steps through the lines of code required to create and publish to a topic
and was created using Xcode version 7.1 and the
Diffusion
Cloud
dynamically linked framework targeted at OS X/macOS. Skip to the full example.
-
Get the
Diffusion
Cloud
Apple®
SDK for OS X/macOS.
This example uses the OS X/macOS framework provided in
diffusion-macosx-version.zip. Frameworks are
also available for
iOS®
-targeted development in
diffusion-iphoneos-version.zip and
tvOS™
-targeted development in
diffusion-tvos-version.zip.
-
Extract the contents of the
diffusion-macosx-version.zip file to your
preferred location for third-party SDKs for use within Xcode.
For example,
~/Documents/code/SDKs/diffusion-macosx-version.
-
Create a new project in Xcode.
-
From the File menu, select
The Choose a template for your new project wizard
opens.
-
Select on the left.
-
Select Command Line Tool on the right and click
Next.
Xcode prompts you to Choose options for your new
project.
-
Configure your project appropriately for your requirements.
Select Objective-C as the
Language.
For example, use the following values:
- Product Name:
CounterPublisher
- Language: Objective-C
-
Click the Next button.
Xcode prompts you to select a destination directory for your new project.
-
Select a target directory.
For example: ~/Documents/code/
-
Click the Create button.
Xcode creates a new project that contains the required files.
-
Link to the
Diffusion
framework.
-
Create a CounterPublisher.h file.
-
Bring up the context menu for the root node of the project in the Project
Navigator in the left sidebar.
Select New File
-
In the dialog that opens, select Header File
-
Name the header file CounterPublisher.h and click
Create.
-
Import the Foundation module into the
CounterPublisher.h file.
-
Define the CounterPublisher interface in the
CounterPublisher.h file.
@interface CounterPublisher : NSObject
-(void)startWithURL:(NSURL *)url;
@end
-
Create a CounterPublisher.m file.
-
Bring up the context menu for the root node of the project in the Project
Navigator in the left sidebar.
Select New File
-
In the dialog that opens, select Objective-C File
-
Name the file CounterPublisher.m and click
Create.
-
In the CounterPublisher.m file, import the required modules and
set up properties and variables.
-
Import Diffusion and CounterPublisher.h
#import "CounterPublisher.h"
@import Diffusion;
-
Define a long-lived session property.
Add the session instance to the class extension to maintain a strong reference to
the session instance:
@interface CounterPublisher ()
@property(nonatomic) PTDiffusionSession* session;
@end
The strong reference ensures that once the session instance has been opened, it
remains open.
-
Declare an integer _counter to hold the value to publish to the
topic.
@implementation CounterPublisher {
NSUInteger _counter;
}
-
Define the topic path of the topic to create and publish to.
static NSString *const _TopicPath = @"foo/counter";
-
In the CounterPublisher.m file, create a method that starts the
session with
Diffusion
Cloud
.
-
Call the method startWithURL and give it a signature that matches
that defined in CounterPublisher.h
-(void)startWithURL:(NSURL *)url {
}
-
Inside the method, define the security principal and credentials that the client
uses to connect.
PTDiffusionCredentials *credentials =
[[PTDiffusionCredentials alloc] initWithPassword:@"password"];
PTDiffusionSessionConfiguration *sessionConfiguration =
[[PTDiffusionSessionConfiguration alloc] initWithPrincipal:@"principal"
credentials:credentials];
Replace principal and password with the
username and password to connect to
Diffusion
Cloud
with. This
user must have sufficient permissions to create and update the topic, for example,
by being assigned the "TOPIC_CONTROL" role.
-
Open a session on
Diffusion
Cloud
.
[PTDiffusionSession openWithURL:url
configuration:sessionConfiguration
completionHandler:^(PTDiffusionSession *session, NSError *error)
{
if (!session) {
NSLog(@"Failed to open session: %@", error);
return;
}
// At this point we now have a connected session.
NSLog(@"Connected.");
// Maintain strong reference to session instance.
self.session = session;
// Next step
}];
-
Create a topic.
After connecting a session and creating a strong reference to it, use
session.topicControl to create a topic:
// Send request to add topic for publishing to.
[session.topicControl addWithTopicPath:_TopicPath
type:PTDiffusionTopicType_SingleValue
value:nil
completionHandler:^(NSError *error)
{
if (error) {
NSLog(@"Failed to add topic: %@", error);
return;
}
// Next step
}];
-
Update the topic.
-
After successfully creating the topic, call the updateCounter
method:
-
At the top-level of the CounterPublisher.m file, define the
updateCounter method:
-(void)updateCounter {
// Get the updater to be used for non-exclusive topic updates.
PTDiffusionTopicUpdater *updater = self.session.topicUpdateControl.updater;
// Format string content for the update.
NSString *string = [NSString stringWithFormat:@"%lu", (unsigned long)_counter++];
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
PTDiffusionContent *content = [[PTDiffusionContent alloc] initWithData:data];
// Send request to update topic.
NSLog(@"Updating: %@", string);
[updater updateWithTopicPath:_TopicPath
value:content
completionHandler:^(NSError *error)
{
if (error) {
NSLog(@"Failed to update topic: %@", error);
}
}];
// Schedule another update in one second's time.
__weak CounterPublisher *const weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(1.0 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^
{
[weakSelf updateCounter];
});
}
This method recursively calls itself via a weak reference to self.
-
In the main.m, add the code needed to run your publishing client
from the command line:
-
Import the Foundation module and the
CounterPublisher.h file.
@import Foundation;
#import "CounterPublisher.h"
-
In a main method, create a CounterPublisher and
call its startWithURL method:
int main(int argc, const char * argv[]) {
@autoreleasepool {
CounterPublisher *const publisher = [CounterPublisher new];
NSURL *const url = [NSURL URLWithString:@"wss://hostname"];
[publisher startWithURL:url];
// Run in an infinite Loop.
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
Replace hostname with the host name of your
Diffusion
Cloud
service.
-
Build and Run.
The client publishes a value to the foo/counter topic every second. You can subscribe to the foo/counter topic by using
the
Diffusion
Cloud Dashboard's test client or by creating a
client to subscribe to the topic. For more information, see Start subscribing with iOS.
Full example
The completed implementation of the publishing
client files contain the following code:
main.m:
@import Foundation;
#import "CounterPublisher.h"
/**
Wrapper around the counter publisher example class demonstrating how it can
be launched as a command line tool.
*/
int main(int argc, const char * argv[]) {
@autoreleasepool {
CounterPublisher *const publisher = [CounterPublisher new];
NSURL *const url = [NSURL URLWithString:@"wss://hostname"];
[publisher startWithURL:url];
// Run, Infinite Loop.
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
CounterPublisher.h:
@import Foundation;
@interface CounterPublisher : NSObject
-(void)startWithURL:(NSURL *)url;
@end
CounterPublisher.m:
@import Diffusion;
@interface CounterPublisher ()
@property(nonatomic) PTDiffusionSession* session;
@end
@implementation CounterPublisher {
NSUInteger _counter;
}
@synthesize session = _session;
static NSString *const _TopicPath = @"foo/counter";
-(void)startWithURL:(NSURL *)url {
NSLog(@"Connecting...");
// Connect with control client credentials.
PTDiffusionCredentials *credentials =
[[PTDiffusionCredentials alloc] initWithPassword:@"password"];
PTDiffusionSessionConfiguration *sessionConfiguration =
[[PTDiffusionSessionConfiguration alloc] initWithPrincipal:@"principal"
credentials:credentials];
[PTDiffusionSession openWithURL:url
configuration:sessionConfiguration
completionHandler:^(PTDiffusionSession *session, NSError *error)
{
if (!session) {
NSLog(@"Failed to open session: %@", error);
return;
}
// At this point we now have a connected session.
NSLog(@"Connected.");
// Maintain strong reference to session instance.
self.session = session;
// Send request to add topic for publishing to.
[session.topicControl addWithTopicPath:_TopicPath
type:PTDiffusionTopicType_SingleValue
value:nil
completionHandler:^(NSError *error)
{
if (error) {
NSLog(@"Failed to add topic: %@", error);
return;
}
// At this point we now have a topic.
[self updateCounter];
}];
}];
}
-(void)updateCounter {
// Get the updater to be used for non-exclusive topic updates.
PTDiffusionTopicUpdater *updater = self.session.topicUpdateControl.updater;
// Format string content for the update.
NSString *string = [NSString stringWithFormat:@"%lu", (unsigned long)_counter++];
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
PTDiffusionContent *content = [[PTDiffusionContent alloc] initWithData:data];
// Send request to update topic.
NSLog(@"Updating: %@", string);
[updater updateWithTopicPath:_TopicPath
value:content
completionHandler:^(NSError *error)
{
if (error) {
NSLog(@"Failed to update topic: %@", error);
}
}];
// Schedule another update in one second's time.
__weak CounterPublisher *const weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(1.0 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^
{
[weakSelf updateCounter];
});
}
@end