-
Setup your configuration by calling
CfConfiguration
's static methodbuilder()
and pass-in your prefered configuration settings through possible chaining methods. The chaining needs to be ended withbuild()
method. (See thebuild()
's description for possible chaining methods and their default values.) -
Setup your target by calling
CfTarget
's static methodbuilder()
and pass-in your prefered target settings through possible chaining methods. The chaining needs to be ended withbuild()
method. (See thebuild()
's description for possible chaining methods and their default values). Target'sidentifier
is mandatory and represents theAccount
from which you wish to receive evaluations. -
Call
CfClient.sharedInstance.initialize(apiKey:configuration:target:cache:onCompletion:)
and pass in your Harness CFapiKey
, previously created configuration object, target and an optional cache object adoptingStorageRepositoryProtocol
.If
cache
object is omitted, internal built-in cache will be used. You can also omittonCompletion
parameter if you don't need initialization/authorization information.
Your ff-ios-client-sdk
is now initialized. Congratulations!!!
Upon successful initialization and authorization, the completion block of CfClient.sharedInstance.initialize(apiKey:configuration:target:cache:onCompletion:)
will deliver Swift.Result<Void, CFError>
object. You can then switch through it's .success(Void)
and .failure(CFError)
cases and decide on further steps depending on a result.
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
}
}
The Public API exposes few methods that you can utilize:
Please note that all of the below methods are called on CfClient.sharedInstance
-
public func initialize(apiKey:configuration:target:cache:onCompletion:)
-> Called first as described above in the initialization section.(Mandatory)
-
public func registerEventsListener(events:onCompletion:)
-> Called in the ViewController where you would like to receive the events.(Mandatory)
-
public func destroy()
-
public func stringVariation(evaluationId:defaultValue:completion:)
-
public func boolVariation(evaluationId:defaultValue:completion:)
-
public func numberVariation(evaluationId:defaultValue:completion:)
-
public func jsonVariation(evaluationId:defaultValue:completion:)
events
is an array of events that you would like to subscribe to. It defaults to *
, which means ALL events.
In order to be notified of the SSE events sent from the server, you need to call CfClient.sharedInstance.registerEventsListener()
method.
NOTE: Registering to events is usually done in viewDidLoad()
method when events are required in only one ViewController OR viewDidAppear()
if there are more than one registration calls throughout the app, so the events could be re-registered for the currently visible ViewController.
The completion block of this method will deliver Swift.Result<EventType, CFError>
object. You can use switch
statement within it's .success(EventType)
case to distinguish which event has been received and act accordingly as in the example below or handle the error gracefully from it's .failure(CFError)
case.
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
}
}
}
}
The following methods can be used to fetch an Evaluation from cache, by it's known key. Completion handler delivers Evaluation
result. If defaultValue
is specified, it will be returned if key does not exist. If defaultValue
is omitted, nil
will be delivered in the completion block. Fetching is done for specified target identifier during initialize() call.
Use appropriate method to fetch the desired Evaluation of a certain type.
CfClient.sharedInstance.stringVariation("your_evaluation_id", defaultValue: String?) { (evaluation) in
//Make use of the fetched `String` Evaluation
}
CfClient.sharedInstance.boolVariation("your_evaluation_id", defaultValue: Bool?) { (evaluation) in
//Make use of the fetched `Bool` Evaluation
}
CfClient.sharedInstance.numberVariation("your_evaluation_id", defaultValue: Int?) { (evaluation) in
//Make use of the fetched `Int` Evaluation
}
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])
The SDK comes with a basic default logger that logs to info level via os_log(). You can configure debug and trace logs to be shown as
well by setting setDebug(true)
on the configuration builder. However if you need more control over logs or have your own logging system you can integrate with that system by providing
a factory class which instantiates logger instances. The example below uses Apple's swift-log you can use any framework you want.
import Logging
class SwiftLogLogger : SdkLogger {
var logger:Logger
init( label:String) {
logger = Logger(label: label)
logger.logLevel = .trace
}
func trace(_ msg: String) {
logger.trace("🔍 \(msg)")
}
func debug(_ msg: String) {
logger.debug("📗 \(msg)")
}
func info(_ msg: String) {
logger.info("📘 \(msg)")
}
func warn(_ msg: String) {
logger.warning("📕 \(msg)")
}
func error(_ msg: String) {
logger.error("💥 \(msg)")
}
}
class SwiftLogSdkLoggerFactory : SdkLoggerFactory {
func createSdkLogger(_ label: String) -> ff_ios_client_sdk.SdkLogger {
return SwiftLogLogger(label: label)
}
}
let config = CfConfiguration.builder()
.setStreamEnabled(true)
.setAnalyticsEnabled(true)
.setSdkLoggerFactory(SwiftLogSdkLoggerFactory())
.build()
NOTE: Currently only messages originating from the main SDK code are logged. HTTP log messages generated by OpenAPI are not redirected.
To avoid potential memory leak, when SDK is no longer needed (when the app is closed, for example), a caller should call this method.
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()