iOS SDK Reference
- Before You Begin
- Prerequisites
- Use Harness Feature Flag SDKs with iOS Applications
This topic explains how to use the Harness Feature Flag SDK in your iOS application. To learn more about using a Feature Flag SDK with an iOS application, clone and run a sample application from the iOS SDK Github repository.
In this topic:
- Before You Begin
- Prerequisites
- Use Harness Feature Flag SDKs with iOS Applications
- Public API Methods
- Sample Code for iOS Application
Before You Begin
- Feature Flags Overview
- Getting Started with Feature Flags
- Client-Side and Server-Side SDKs
- Communication Strategy Between SDKs and Harness Feature Flags
Prerequisites
- Create a feature flag in Harness. Feature flags wrap your code and allow you to manage the feature release in a controlled way. See Create a Feature Flag.
- Ensure that you have created your SDK Key. See Create an SDK Key.
- Download Harness Feature Flag iOS Client SDK.
- An iOS application to test your feature flag. If you do not have your iOS Application, you can download a sample application from the iOS SDK GitHub repository.
Use Harness Feature Flag SDKs with iOS Applications
Perform the following steps to get started with using the Feature Flags SDK in your iOS application:
Step 1: Install the iOS Feature Flag Client SDK Dependencies
The first step is to install the Feature Flag SDK as a dependency in your application. You can use any of the following methods to install the SDK in your application.
- Swift Package Manager (SPM)
- CocoaPods
- Carthage
Swift Package Manager
The Swift Package Manager is a dependency manager integrated into the swift
compiler and Xcode
. A dependency consists of a relative or absolute URL to the source of the package and a set of requirements for the version of the package that can be used.
You can install the SDK through Xcode or include it as a dependency in your Package.swift
file.
Using Xcode:
To add a package dependency to your Xcode project, select File > Swift Packages > Add Package Dependency and enter the iOS SDK repository clone URL, then select your desired version constraints.
Using Package.swift
File:
To include SDK as a dependency in a Package.swift
file, add ff-ios-client-sdk
to the dependencies section of your Package.swift
file.
dependencies: [
.package(url: "https://github.com/drone/ff-ios-client-sdk.git", .upToNextMinor(from: "0.0.5"))
]
Cocoapods
CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. CocoaPods is built with Ruby and it will be installable with the default Ruby available on macOS. You can use a Ruby Version manager, however, we recommend that you use the standard Ruby available on macOS.
Perform the following steps to install the dependencies:
- If you are using the default Ruby, you need to use
sudo
when installing the gems.$ sudo gem install cocoapods
- Once Cocoapods is installed, create a
Podfile
in your root project folder.$ pod init
- Import
ff-ios-client-sdk
to your.xcproject
. To do so, simply addff-ios-client-sdk
to your newly created Podfile and save the Podfile changes.platform :ios, '10.0'
use_frameworks!
target 'MyApp' do
pod 'ff-ios-client-sdk'
end - Install the packages.
$ pod install
Ensure that you are using.xcworkspace
instead of your.xcodeproj
to utilize the imported Pods.
Carthage
Carthage is intended to be the simplest way to add frameworks to your Cocoa application. Perform the following steps to integrate ff-ios-client-sdk
into your application.
- Navigate to the root folder of your project and create a
Cartfile
. This is the file where you would input all of the dependencies that you plan to use with Carthage.$ touch Cartfile
- Add the following line to your
Cartfile
.github "drone/ff-ios-client-sdk"
- Fetch the source for
ff-ios-client-sdk
from the repository specified in theCartfile
.$ carthage update --no-build
A new folderCarthage
is created at the same location as ofCartfile
and.xcodeproj
. In theCarthage
folder,Checkout
folder is created which has the source code. - Create a project for
ff-ios-client-sdk
dependency.- Run the following command from your project's root folder:
//From your project's root folder
$ cd Carthage/Checkouts/ff-ios-client-sdk - After that, run the following command:
$ swift package generate-xcodeproj
- Or, you can enter it all on the same line.
//From your project's root folder
$ cd Carthage/Checkouts/ff-ios-client-sdk && swift package generate-xcodeproj
- Run the following command from your project's root folder:
- Build the project and place it in the
Build
folder next toCheckouts
. Run the following command from your project's root folder:$ carthage build --use-xcframeworks --platform iOS
- In your application targets’ General tab, in the Frameworks, Libraries, and Embedded Content, drag and drop the
.xcframework
file from theCarthage/Build
folder. - In Embed, select Embed & Sign.
- Import the
ff_ios_client_sdk
. - (Optional) When a new version of
ff-ios-client-sdk
is available and you wish to update this dependency, run:$ carthage update --use-xcframeworks --platform iOS
Step 2: Import the Feature Flag Client in Your Application Code
Import the client using the following command:
import ff_ios_client_sdk
Step 3: Initialize the SDK
Now that the SDK is imported, you can configure and initialize it. You should enter your SDK keys when configuring the SDK so that your application is authorized to connect to Harness Feature Flags and retrieve flags for your environment.
initialize(apiKey:configuration:cache:onCompletion:)
let configuration = CfConfiguration.builder().setStreamEnabled(true).build()
let target = CfTarget.builder().setIdentifier("YOUR_ACCOUNT_IDENTIFIER").build()
CfClient.sharedInstance.initialize(apiKey: "YOUR_API_KEY", configuration: configuration, target: target) { (result) in
switch result {
case .failure(let error):
//Do something to gracefully handle initialization/authorization failure
case .success:
//Continue to the next step after successful initialization/authorization
}
}
Step 4: Evaluate Target for Your Feature Flag
Once you have initialized the CF client for a target, evaluate it for your feature flag. A feature flag is evaluated for a particular target.
Evaluation is performed based on the variation types. In case there is no evaluation with the provided ID, the default value is returned. Use the appropriate method to fetch the desired evaluation of a certain type.
String Variation
CfClient.sharedInstance.stringVariation("your_evaluation_id", defaultValue: String?) { (evaluation) in
//Make use of the fetched `String` Evaluation
}
Boolean Variation
CfClient.sharedInstance.boolVariation("your_evaluation_id", defaultValue: Bool?) { (evaluation) in
//Make use of the fetched `Bool` Evaluation
}
Number Variation
CfClient.sharedInstance.numberVariation("your_evaluation_id", defaultValue: Int?) { (evaluation) in
//Make use of the fetched `Int` Evaluation
}
JSON Variation
CfClient.sharedInstance.jsonVariation("your_evaluation_id", defaultValue: [String:ValueType]?) { (evaluation) in
//Make use of the fetched `[String:ValueType]` Evaluation
}
ValueType
can be one of the following:
- ValueType.bool(Bool)
- ValueType.string(String)
- ValueType.int(Int)
- ValueType.object([String:ValueType])
Step 5: Add Method to Register the Events
This method provides a way to register a listener for different events that might be triggered by SDK, indicating a specific change in the SDK.
CfClient.sharedInstance.registerEventsListener() { (result) in
switch result {
case .failure(let error):
//Gracefully handle error
case .success(let eventType):
switch eventType {
case .onPolling(let evaluations):
//Received all evaluation flags -> [Evaluation]
case .onEventListener(let evaluation):
//Received an evaluation flag -> Evaluation
case .onComplete:
//Received a completion event, meaning that the
//SSE has been disconnected
case .onOpen(_):
//SSE connection has been established and is active
case .onMessage(let messageObj):
//An empty Message object has been received
}
}
}
}
Step 6: Shut Down the SDK
When SDK is not needed, for example, when the app is not running, you can shut down the SDK. This can avoid potential memory leaks.
Also, you need to call this method when changing accounts through CfTarget
object, in order to re-initialize and fetch Evaluations for the right account.
CfClient.sharedInstance.destroy()
Step 7: Verify Your Feature Flag
Run the application from your IDE and verify whether the flag variation value displayed on your application page is consistent with the feature flag you created.
Toggle the flag on and off to verify if your application is getting updated.
Public API Methods
You can also use the public API methods to initialize and implement the Feature Flag iOS SDKs. The Public API exposes the following methods that you can utilize:
public func initialize(apiKey:configuration:target:cache:onCompletion:)
public func stringVariation(evaluationId:defaultValue:completion:)
public func boolVariation(evaluationId:defaultValue:completion:)
public func numberVariation(evaluationId:defaultValue:completion:)
public func jsonVariation(evaluationId:defaultValue:completion:)
public func registerEventsListener(events:onCompletion:)
public func destroy()
Sample Code for iOS Application
Here is a sample code for using Harness Feature Flag SDKs with the iOS application. To learn more about using the sample iOS application, see the iOS SDK Github repository.
import UIKit
import ff_ios_client_sdk
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSLog("Start")
let config = CfConfiguration.builder()
.setStreamEnabled(true)
.build()
let target = CfTarget.builder().setIdentifier("Harness").build()
CfClient.sharedInstance.initialize(
apiKey: "YOUR_API_KEY,
configuration:config,
target: target
) { [weak self] result in
switch result {
case .failure(let error):
NSLog("End: Error \(error)")
case .success():
NSLog("Init: Ok")
CfClient.sharedInstance.boolVariation(evaluationId: "EVALUATION_ID", { (eval) in
print("Value: \(eval!)")
})
CfClient.sharedInstance.registerEventsListener() { (result) in
switch result {
case .failure(let error):
print(error)
case .success(let eventType):
switch eventType {
case .onPolling:
print("Event: Received all evaluation flags")
case .onEventListener(let evaluation):
print("Event: Received an evaluation flag, \(evaluation!)")
case .onComplete:
print("Event: SSE stream has completed")
case .onOpen:
print("Event: SSE stream has been opened")
case .onMessage(let messageObj):
print(messageObj?.event ?? "Event: Message received")
}
}
}
}
}
}
override func viewWillDisappear(_ animated: Bool) {
CfClient.sharedInstance.destroy()
NSLog("End: Ok")
super.viewWillDisappear(animated)
}
}