SwiftSwift Native SDK 3.0.1

 
These docs are for the new PubNub Swift SDK written purely in Swift. To view the docs for the older version (the PubNub Objective-C SDK wrapper for Swift), have a look here.

The Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies. To integrate PubNub into your Xcode project using Swift Package Manager, specify it in the dependencies list of your Package.swift file:

dependencies: [
  .package(url: "https://github.com/pubnub/swift.git", from: "3.0.1")
]

To integrate PubNub into your Xcode project using Embedded Framework, do the following:

  1. In your top-level project directory add PubNub as a submodule:
    $ git submodule add https://github.com/pubnub/swift.git
  2. Open your app’s Xcode project.
  3. In Finder, locate the PubNub.xcodeproj Xcode project inside the submodule directory, and drag it onto your app's project in the Project Navigator.

    PubNub.xcodeproj

    This nests a reference to the framework project in the app project.

  4. Select your app's project in the Project Navigator (blue project icon), navigate to the target configuration window, and select the application target under the "Targets" heading in the sidebar.
  5. Select your application project in the Project Navigator, and then select your application's Target under the TARGETS panel.
  6. Select the General tab in the top middle of the window, and then click the + inside the EMBEDDED BINARIES section
  7. Select the PubNub.framework that is nested inside the top-most PubNub.xcodeproj/Products/ directory

For more information see Apple's guide on Adding Package Dependencies to Your App

CocoaPods is a dependency manager and this is by far the easiest and quickest way to get started with PubNub SDK! (If you don't have pods installed yet you can check CocoaPods installation section for installation guide).

To integrate PubNub into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'PubNubSwift', '~> 3.0.1'

Carthage builds your dependencies and provides you with binary frameworks, but you retain full control over your project structure and setup. Carthage does not automatically modify your project files or your build settings. To integrate PubNub into your Xcode project using Carthage, specify it in your Cartfile:

github "pubnub/swift" ~> 3.0.1


View Supported Platforms
To add the PubNub SDK to your project with Swift Package Manager, do the following:
  1. Create a new Xcode project.
    Create the project as a Single View App, using a Storyboard user interface.

    Xcode project setup
  2. File -> Swift Packages -> Add Package Dependency...
  3. Search for PubNub and select the swift package owned by pubnub, and click Next.
  4. Use the Up to Next Major Version rule spanning from 2.5.0 < 3.0.0, and click Next.
  5. Import the module named PubNub inside your AppDelegate:

    import UIKit
    import PubNub // <- Here is our PubNub module import.
  6. Create a global PubNub object and pass it to your root view controller:

     Always set the UUID to uniquely identify the user or device that connects to PubNub. This UUID should be persisted, and should remain unchanged for the lifetime of the user or the device. Not setting the UUID can significantly impact your billing if your account uses the Monthly Active Users (MAUs) based pricing model, and can also lead to unexpected behavior if you have Presence enabled.
    import UIKit
    import PubNub
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
      var pubnub: PubNub!
      var window: UIWindow?
    
      func application(_ application: UIApplication,
                       willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        PubNub.log.levels = [.all]
        PubNub.log.writers = [ConsoleLogWriter(), FileLogWriter()]
    
        var config = PubNubConfiguration(publishKey: "demo", subscribeKey: "demo")
        pubnub = PubNub(configuration: config)
    
        if #available(iOS 13.0, *) {
          // no-op - UI created in scene delegate
        } else if let rootVC = self.window?.rootViewController as? ViewController {
          rootVC.pubnub = pubnub
        }
    
        return true
      }
    
      // MARK: UISceneSession Lifecycle
    
      @available(iOS 13.0, *)
      func application(_ application: UIApplication,
                       configurationForConnecting connectingSceneSession: UISceneSession, 
                       options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
      }
    
      @available(iOS 13.0, *)
      func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // no-op
      }
    }
  7. If using multiple Scenes, use the SceneDelegate to pass your PubNub instance to your view controllers:

     Always set the UUID to uniquely identify the user or device that connects to PubNub. This UUID should be persisted, and should remain unchanged for the lifetime of the user or the device. Not setting the UUID can significantly impact your billing if your account uses the Monthly Active Users (MAUs) based pricing model, and can also lead to unexpected behavior if you have Presence enabled.
    import UIKit
    import PubNub
    
    @available(iOS 13.0, *)
    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
      var window: UIWindow?
      var pubnub: PubNub?
    
      func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScence = scene as? UIWindowScene, let pubnub = (UIApplication.shared.delegate as? AppDelegate)?.pubnub else { return }
        let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    
        let rootVC = mainStoryboard.instantiateInitialViewController() as? ViewController
        rootVC?.pubnub = pubnub
    
        let window = UIWindow(windowScene: windowScence)
        window.rootViewController = rootVC
        window.makeKeyAndVisible()
    
        self.window = window
      }
    }
  8. Set up your ViewController.

    
    
    import UIKit
    import PubNub
    
    class ViewController: UIViewController {
    
      var pubnub: PubNub!
      let channels = ["awesomeChannel"]
      let listener = SubscriptionListener(queue: .main)
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        listener.didReceiveMessage = { message in
          print("[Message]: \(message)")
        }
        listener.didReceiveStatus = { status in
          switch status {
          case .success(let connection):
            if connection == .connected {
              self.pubnub.publish(channel: self.channels[0], message: "Hello, PubNub Swift!") { result in
                print(result.map { "Publish Response at \($0.timetoken.timetokenDate)" })
              }
            }
          case .failure(let error):
            print("Status Error: \(error.localizedDescription)")
          }
        }
    
        pubnub.add(listener)
    
        pubnub.subscribe(to: channels, withPresence: true)
      }
    }
import UIKit
import PubNub

class ViewController: UIViewController {

  var pubnub: PubNub!
  let channels = ["awesomeChannel"]
  let listener = SubscriptionListener(queue: .main)

  override func viewDidLoad() {
    super.viewDidLoad()

    listener.didReceiveMessage = { message in
      print("[Message]: \(message)")
    }
    listener.didReceiveStatus = { status in
      switch status {
      case .success(let connection):
        if connection == .connected {
          self.pubnub.publish(channel: self.channels[0], message: "Hello, PubNub Swift!") { result in
            print(result.map { "Publish Response at \($0.timetoken.timetokenDate)" })
          }
        }
      case .failure(let error):
        print("Status Error: \(error.localizedDescription)")
      }
    }

    pubnub.add(listener)

    pubnub.subscribe(to: channels, withPresence: true)
  }
}
In addition to the Hello World sample code, we also provide some copy and paste snippets of common API functions:

Instantiate a new Pubnub instance. Only the subscribeKey is mandatory. Also include publishKey if you intend to publish from this instance.

 Always set the UUID to uniquely identify the user or device that connects to PubNub. This UUID should be persisted, and should remain unchanged for the lifetime of the user or the device. Not setting the UUID can significantly impact your billing if your account uses the Monthly Active Users (MAUs) based pricing model, and can also lead to unexpected behavior if you have Presence enabled.
var config = PubNubConfiguration(
  publishKey: "demo",
  subscribeKey: "demo"
)
config.uuid = "myUniqueUUID"
let pubnub = PubNub(configuration: config)
// Create a new listener instance
let listener = SubscriptionListener()

// Add listener event callbacks
listener.didReceiveSubscription = { event in
  switch event {
  case let .messageReceived(message):
    print("Message Received: \(message) Publisher: \(message.publisher ?? "defaultUUID")")
  case let .connectionStatusChanged(status):
    print("Status Received: \(status)")
  case let .presenceChanged(presence):
    print("Presence Received: \(presence)")
  case let .subscribeError(error):
    print("Subscription Error \(error)")
  default:
    break
  }
}

// Start receiving subscription events
pubnub.add(listener)
     

    You can check the UUID of the publisher of a particular message by checking the message.publisher property in the subscription listener. Note that you must also provide a default value for publisher, as the uuid parameter is optional.

The SubscriptionListener can be removed by either calling listener.cancel(), or by letting it fall out of scope and be removed as an autoreleased object.

This is the list of event case types that can be emitted from didReceiveSubscription. Each event case also has a standalone listener that can save code space, but will be functionally equivalent to using didReceiveSubscription.

Event CaseEvent TypeStandalone ListenerEvent Description
messageReceivedMessageEventdidReceiveMessageMessages sent to subscribed channels/groups
signalReceivedMessageEventdidReceiveSignalSignals sent to subscribed channels/groups
connectionStatusChangedConnectionStatusdidReceiveStatusChanges in the connection to the PubNub system
subscriptionChangedSubscriptionChangeEventdidReceiveSubscriptionChangeNotifies when channels/groups are subscribed or unsubscribed
presenceChangedPresenceEventdidReceivePresencePresence changes on subscribed channels/groups tracking presence
userUpdatedUserEventdidReceiveUserEventA subscribed User was updated
userDeletedIdentifierEventdidReceiveUserEventA subscribed User was deleted
spaceUpdatedSpaceEvendidReceiveSpaceEventA subscribed Space was updated
spaceDeletedIdentifierEventdidReceiveSpaceEventA subscribed Space was deleted
membershipAddedMembershipEventdidReceiveMembershipEventA new membership was created
membershipUpdatedMembershipEventdidReceiveMembershipEventAn existing membership was updated
membershipDeletedMembershipIdentifiabledidReceiveMembershipEventAn existing membership was deleted
subscribeErrorPubNubErrorsubscribeErrorAny error that might have occurred during the subscription stream
messageActionAddedMessageActionEventdidReceiveMessageActionA MessageAction was added to a published message
messageActionRemovedMessageActionEventdidReceiveMessageActionA MessageAction was removed from a published message
Call pubnub.time to verify the client connectivity to the origin:
pubnub.time { result in
  switch result {
  case let .success(response):
    print("Handle downloaded server time token using: \(response.timetoken)")
  case let .failure(error):
    print("Handle response error: \(error.localizedDescription)")
  }
}
pubnub.subscribe(to: ["my_channel"])
The response of the call is handled by adding a Listener. Please see the Listeners section for more details. Listeners should be added before calling the method.
Publish a message to a channel:
pubnub.publish(channel: "my_channel", message: "Test Message!") { result in
  switch result {
  case let .success(response):
    print("Handle successful Publish response: \(response)")
  case let .failure(error):
    print("Handle response error: \(error.localizedDescription)")
  }
}
Get occupancy of who's here now on the channel by UUID:
Requires you to enable the Presence add-on for your key. Refer to the How do I enable add-on features for my keys? knowledge base article for details on enabling features.
pubnub.hereNow(on: ["my_channel"]) { result in
  switch result {
  case let .success(response):
    print("Successful hereNow Response: \(response)")
  case let .failure(error):
    print("Failed hereNow Response: \(error.localizedDescription)")
  }
})
Subscribe to realtime Presence events, such as join, leave, and timeout, by UUID. Setting the presence attribute to a callback will subscribe to presents events on my_channel:
Requires you to enable the Presence add-on for your key. Refer to the How do I enable add-on features for my keys? knowledge base article for details on enabling features.
pubnub.subscribe(
  to: ["my_channel"],
  withPresence: true
)
The response of the call is handled by adding a Listener. Please see the Listeners section for more details. Listeners should be added before calling the method.
Retrieve published messages from archival storage:
Requires that the Storage and Playback add-on is enabled for your key. How do I enable add-on features for my keys? - see http://www.pubnub.com/knowledge-base/discussion/644/how-do-i-enable-add-on-features-for-my-keys
pubnub.fetchMessageHistory(for: ["my_channel"]) { result in
  switch result {
  case let .success(response):
    print("Successful History Fetch Response: \(response)")
  case let .failure(error):
    print("Failed History Fetch Response: \(error.localizedDescription)")
  }
})
pubnub.unsubscribe(from: ["my_channel"])
The response of the call is handled by adding a Listener. Please see the Listeners section for more details. Listeners should be added before calling the method.