Skip to content

Latest commit

 

History

History
180 lines (143 loc) · 8 KB

further_reading.md

File metadata and controls

180 lines (143 loc) · 8 KB

Further Reading

Initialization

  1. Setup your configuration by calling CfConfiguration's static method builder() and pass-in your prefered configuration settings through possible chaining methods. The chaining needs to be ended with build() method. (See the build()'s description for possible chaining methods and their default values.)

  2. Setup your target by calling CfTarget's static method builder() and pass-in your prefered target settings through possible chaining methods. The chaining needs to be ended with build() method. (See the build()'s description for possible chaining methods and their default values). Target's identifier is mandatory and represents the Account from which you wish to receive evaluations.

  3. Call CfClient.sharedInstance.initialize(apiKey:configuration:target:cache:onCompletion:) and pass in your Harness CF apiKey, previously created configuration object, target and an optional cache object adopting StorageRepositoryProtocol.

    If cache object is omitted, internal built-in cache will be used. You can also omitt onCompletion 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.

 

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
	}
}

Implementation

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()

    Fetching from cache methods


  • public func stringVariation(evaluationId:defaultValue:completion:)

  • public func boolVariation(evaluationId:defaultValue:completion:)

  • public func numberVariation(evaluationId:defaultValue:completion:)

  • public func jsonVariation(evaluationId:defaultValue:completion:)

 

registerEventsListener(events:onCompletion:)

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
			}
		}
	}
}

Fetching from cache methods

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.

stringVariation(forKey:defaultValue:completion:)

CfClient.sharedInstance.stringVariation("your_evaluation_id", defaultValue: String?) { (evaluation) in
	//Make use of the fetched `String` Evaluation
}

boolVariation(forKey:defaultValue:completion:)

CfClient.sharedInstance.boolVariation("your_evaluation_id", defaultValue: Bool?) { (evaluation) in
	//Make use of the fetched `Bool` Evaluation
}

numberVariation(forKey:defaultValue:completion:)

CfClient.sharedInstance.numberVariation("your_evaluation_id", defaultValue: Int?) { (evaluation) in
	//Make use of the fetched `Int` Evaluation
}

jsonVariation(forKey:defaultValue:completion:)

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])

Custom Loggers

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.

Shutting down the SDK

destroy()

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()