Functions

The following functions are available globally.

  • Target availability: iOS apps.

    You must call APLApplicationDidFinishLaunchingWithOptions() in your app delegate’s application:didFinishLaunchingWithOptions: method.

    Objective-C example

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      APLApplicationDidFinishLaunchingWithOptions(launchOptions);
      return YES;
    }
    

    Swift example

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
      APLApplicationDidFinishLaunchingWithOptions(launchOptions)
      return true
    }
    

    Declaration

    Objective-C

    extern void APLApplicationDidFinishLaunchingWithOptions(
        NSDictionary *_Nullable launchOptions)

    Swift

    func APLApplicationDidFinishLaunchingWithOptions(_ launchOptions: [AnyHashable : Any]?)
  • Target availability: iOS apps.

    You must call APLApplicationOpenURL() in your app delegate’s application:openURL:options: method.

    Objective-C example

    - (BOOL) application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
      return APLApplicationOpenURL(url);
    }
    

    Swift example

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
      return APLApplicationOpenURL(url)
    }
    

    Declaration

    Objective-C

    extern BOOL APLApplicationOpenURL(NSURL *_Nonnull url)

    Swift

    func APLApplicationOpenURL(_ url: URL) -> Bool
  • Target availability: watchOS apps.

    You must call APLApplicationDidFinishLaunching() in your extension’s delegate applicationDidFinishLaunching method.

    Objective-C example

    - (void) applicationDidFinishLaunching {
      APLApplicationDidFinishLaunching();
    }
    

    Swift example

    func applicationDidFinishLaunching() {
      APLApplicationDidFinishLaunching()
    }
    

    Declaration

    Objective-C

    extern void APLApplicationDidFinishLaunching(void)

    Swift

    func APLApplicationDidFinishLaunching()
  • Target availability: watchOS apps.

    Receives configuration commands and payloads from the paired iPhone’s Appfigurate app.

    If your watch app has its own WCSessionDelegate, then call the APLSessionDidReceiveMessage() function from within your session:didReceiveMessage:replyHandler: method (see examples below). If your watch app does not have its own WCSessionDelegate then you do not need to do anything - Appfigurate library installs a WCSessionDelegate and calls APLSessionDidReceiveMessage() automatically.

    Objective-C example

    - (void) session: (WCSession*) session didReceiveMessage: (NSDictionary<NSString*,id>*) message
       replyHandler: (void (^)(NSDictionary<NSString*,id>*)) replyHandler {
       NSDictionary* reply = APLSessionDidReceiveMessage(message);
       if (reply != nil)
           replyHandler(reply);
       else
          ...
    

    Swift example

    func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
      let reply = APLSessionDidReceiveMessage(message)
      if reply != nil {
        replyHandler(reply)
      } else {
        ...
    

    Declaration

    Objective-C

    extern NSDictionary *_Nullable APLSessionDidReceiveMessage(
        NSDictionary<NSString *, id> *_Nonnull message)

    Swift

    func APLSessionDidReceiveMessage(_ message: [String : Any]) -> [AnyHashable : Any]?
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Returns the version of the Appfigurate library in the format “major.minor.patch”. e.g. “5.1.2”

    Declaration

    Objective-C

    extern NSString *_Nonnull APLVersion(void)

    Swift

    func APLVersion() -> String
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Registers a delegate method that will be called back when Appfigurate has updated the configuration of the app or extension. See also APLAddConfigurationUpdatedBlock() function for block based callback.

    Declaration

    Objective-C

    extern void
    APLAddConfigurationUpdatedListener(id<APLConfigurationUpdated> _Nonnull target)

    Swift

    func APLAddConfigurationUpdatedListener(_ target: any APLConfigurationUpdated)
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Registers a block that will be called back when Appfigurate has updated the configuration of the app or extension. Returns an opaque object to act as the observer. See also APLRemoveConfigurationUpdatedBlock().

    Declaration

    Objective-C

    extern id<NSObject> _Nonnull APLAddConfigurationUpdatedBlock(
        APLConfigurationUpdatedBlock _Nonnull block)

    Swift

    func APLAddConfigurationUpdatedBlock(_ block: @escaping APLConfigurationUpdatedBlock) -> any NSObjectProtocol
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Unregisters the delegate method that will be called back when Appfigurate has updated the configuration of the application. You may optionally call this method before the target is deallocated.

    Declaration

    Objective-C

    extern void APLRemoveConfigurationUpdatedListener(
        id<APLConfigurationUpdated> _Nonnull target)

    Swift

    func APLRemoveConfigurationUpdatedListener(_ target: any APLConfigurationUpdated)
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Unregisters the block that will be called back when Appfigurate has updated the configuration of the application. You must call this method before the block is deallocated. The observer argument is the result of APLAddConfigurationUpdatedBlock().

    Declaration

    Objective-C

    extern void APLRemoveConfigurationUpdatedBlock(id<NSObject> _Nonnull observer)

    Swift

    func APLRemoveConfigurationUpdatedBlock(_ observer: any NSObjectProtocol)
  • Target availability: iOS apps.

    When integrating with third party remote configuration providers, you must specify a block that is called back whenever Appfigurate requires the current value of a third party remote configuration property. The block will be called for each REMOTE_BOOL_PROPERTY, REMOTE_XXXX_PROPERTY_EDIT macro (Objective-C) or @RemoteBoolProperty, @RemoteXXXXPropertyEdit property wrapper (Swift) you have specified in your APLConfiguration subclass.

    REMOTE_BOOL_PROPERTY/@RemoteBoolProperty              ‣ APLRemotePropertyTypeBool   ‣ [NSNumber boolValue]    ‣ BOOL/Bool
    REMOTE_INT_PROPERTY_EDIT/@RemoteIntPropertyEdit       ‣ APLRemotePropertyTypeInt    ‣ [NSNumber integerValue] ‣ NSInteger/Int
    REMOTE_DOUBLE_PROPERTY_EDIT/@RemoteDoublePropertyEdit ‣ APLRemotePropertyTypeDouble ‣ [NSNumber doubleValue]  ‣ double/Double
    REMOTE_STRING_PROPERTY_EDIT/@RemoteStringPropertyEdit ‣ APLRemotePropertyTypeString ‣ NSString                ‣ NSString/String
    

    propertyKey is the name of the remote property in the third party provider’s system. propertyType will be one of the APLRemotePropertyType enumerations indicating the exact type of the property. defaultValue will be the value specified by the subclasses -[APLConfiguration reset] method.

    Objective-C Firebase Remote Config example

    APLFetchRemoteConfiguration(^NSObject* (NSString* propertyKey, APLRemotePropertyType propertyType, NSObject* defaultValue) {
      if (propertyType == APLRemotePropertyTypeString) {
        return [self.remoteConfig configValueForKey: propertyKey].stringValue;
      } else if (propertyType == APLRemotePropertyTypeBool) {
        return [NSNumber numberWithBool: [self.remoteConfig configValueForKey: propertyKey].boolValue];
      } else // APLRemotePropertyTypeInt || APLRemotePropertyTypeDouble {
        return [self.remoteConfig configValueForKey: propertyKey].numberValue;
      }
    });
    

    Swift Firebase Remote Config example

    APLFetchRemoteConfiguration { propertyKey, propertyType, _ in
      if propertyType == .string {
        return self.remoteConfig.configValue(forKey: propertyKey).stringValue! as NSObject
      } else if propertyType == .bool {
        return self.remoteConfig.configValue(forKey: propertyKey).boolValue as NSObject
      } else { // .int || .double
        return self.remoteConfig.configValue(forKey: propertyKey).numberValue as NSObject
      }
    }
    

    Objective-C Launch Darkly example

    APLFetchRemoteConfiguration(^NSObject* (NSString* propertyKey, APLRemotePropertyType propertyType, NSObject* defaultValue) {
      if (propertyType == APLRemotePropertyTypeBool) {
        return [NSNumber numberWithBool: [[LDClient get] boolVariationForKey: propertyKey defaultValue: [((NSNumber*) defaultValue) boolValue]]];
      } else if (propertyType == APLRemotePropertyTypeInt) {
        return [NSNumber numberWithInteger: [[LDClient get] integerVariationForKey: propertyKey defaultValue: [((NSNumber*) defaultValue) integerValue]]];
      } else if (propertyType == APLRemotePropertyTypeDouble) {
        return [NSNumber numberWithDouble: [[LDClient get] doubleVariationForKey: propertyKey defaultValue: [((NSNumber*) defaultValue) doubleValue]]];
      } else {
        return [[LDClient get] stringVariationForKey: propertyKey defaultValue: (NSString*) defaultValue];
      }
    });
    

    Swift Launch Darkly example

    APLFetchRemoteConfiguration { propertyKey, propertyType, defaultValue in
      if propertyType == .bool {
        return NSNumber(value: (LDClient.get()!.boolVariation(forKey: propertyKey, defaultValue: (defaultValue as! NSNumber).boolValue)))
      } else if propertyType == .int {
        return NSNumber(value: (LDClient.get()!.intVariation(forKey: propertyKey, defaultValue: (defaultValue as! NSNumber).intValue)))
      } else if propertyType == .double {
        return NSNumber(value: (LDClient.get()!.doubleVariation(forKey: propertyKey, defaultValue: (defaultValue as! NSNumber).doubleValue)))
      } else {
        return NSString(string: LDClient.get()!.stringVariation(forKey: propertyKey, defaultValue: (defaultValue as! String)))
      }
    }
    

    Declaration

    Objective-C

    extern void APLFetchRemoteConfiguration(NSObject *_Nonnull (^_Nullable)(
        NSString *_Nonnull, APLRemotePropertyType, NSObject *_Nonnull))

    Swift

    func APLFetchRemoteConfiguration(_: ((String, APLRemotePropertyType, NSObject) -> NSObject)?)
  • Target availability: iOS apps.

    You must call the APLFlushRemoteConfiguration() function anytime your third party remote configuration provider has received & activated remote configuration. Forces the callback passed into APLFetchRemoteConfiguration() to be invoked to reload the new values of third party remote configuration properties.

    Objective-C Firebase Remote Config example

    [remoteConfig activateWithCompletion: ^(BOOL changed, NSError* error) {
      ...
      APLFlushRemoteConfiguration();
    }];
    

    Swift Firebase Remote Config example

    remoteConfig.activate { changed, error in
      ...
      APLFlushRemoteConfiguration()
    }
    

    Objective-C Launch Darkly example

    [LDClient startWithConfiguration:config context:context startWaitSeconds:5.0 completion:^(bool timedOut) {
      ...
      APLFlushRemoteConfiguration();
    }];
    
    [[LDClient get] observeAllKeysWithOwner: self handler:^(NSDictionary<NSString *,LDChangedFlag *> *handler) {
      ...
      APLFlushRemoteConfiguration();
    }];
    

    Swift Launch Darkly example

    LDClient.start(config: config, startWaitSeconds: 5.0) { timedOut in
      if !timedOut {
        ...
        APLFlushRemoteConfiguration()
      }
    }
    
    LDClient.get()?.observeAll(owner: self) { keys in
      ...
      APLFlushRemoteConfiguration()
    }
    

    Declaration

    Objective-C

    extern void APLFlushRemoteConfiguration(void)

    Swift

    func APLFlushRemoteConfiguration()
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Saves the configuration persisted in the keychain into temporary storage. Some apps have functionality to erase the keychain to reset apps back to “factory defaults”, which has the side effect of removing any Appfigurate configuration persisted in the keychain. Usage example:

    Objective-C example

    - (void) eraseKeychain {
      APLSaveConfiguration();
      NSArray* secItemClasses = @[(__bridge id) kSecClassGenericPassword,
        (__bridge id) kSecClassInternetPassword,
        (__bridge id) kSecClassCertificate,
        (__bridge id) kSecClassKey,
        (__bridge id) kSecClassIdentity];
      for (id secItemClass in secItemClasses) {
        NSDictionary *spec = @{(__bridge id)kSecClass: secItemClass};
        SecItemDelete((__bridge CFDictionaryRef)spec);
      }
      APLRestoreConfiguration();
    }
    

    Declaration

    Objective-C

    extern void APLSaveConfiguration(void)

    Swift

    func APLSaveConfiguration()
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    Restores the configuration from temporary storage back into the keychain. See also APLSaveConfiguration() for more details and usage example.

    Declaration

    Objective-C

    extern void APLRestoreConfiguration(void)

    Swift

    func APLRestoreConfiguration()
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    The application or framework that links the static AppfigurateLibrary.xcframework must define a function with the following prototype that returns the Class (Objective-C) or AnyClass (Swift) of your APLConfiguration subclass.

    Objective-C example

    - (Class) _Nonnull APLConfigurationClass(void) {
      return [ExampleConfiguration class];
    }
    

    Swift example

    @_cdecl("APLConfigurationClass")
    func APLConfigurationClass() -> AnyClass {
      return ExampleConfiguration.self
    }
    

    Declaration

    Objective-C

    extern Class _Nonnull APLConfigurationClass(void)

    Swift

    func APLConfigurationClass() -> AnyClass
  • Target availability: iOS XCUITest automation testing.

    Sends a message to the application under test, and waits for a response. You can only call this function from within an XCUITest automation test case. name is the message name, must not be nil or blank, maximum 255 bytes after encoding with UTF-8. plist is a property list object or nil. timeout is the duration in seconds you expect to receive a response, otherwise an AppfigurateLibraryException is thrown (minimum of 3.0 seconds). Returns a property list object or nil from the application under test. See also APLAutomationMessageReceivedBlock().

    Objective-C example

    - (void) testLogin {
      XCUIApplication *app = [XCUIApplication new];
      [app launch];
    
      APLAutomationSendMessage(@"SetResponseData", @{
        @"Request": @"/login",
        @"Status": [NSNumber numberWithInt: 200],
        @"Response": @"{'Customer':'2311569'}"
      }, 3.0);
      ...
    

    Swift example

    func testLogin() {
      var app = XCUIApplication()
      app.launch
    
      APLAutomationSendMessage("SetResponseData", [
        "Request": "/login",
        "Status": 200,
        "Response": "{'Customer':'2311569'}"
      ], 3.0)
      ...
    

    Declaration

    Objective-C

    extern id _Nullable APLAutomationSendMessage(NSString *_Nonnull name,
                                                 id _Nullable plist,
                                                 NSTimeInterval timeout)

    Swift

    func APLAutomationSendMessage(_ name: String, _ plist: Any?, _ timeout: TimeInterval) -> Any?
  • Target availability: iOS XCUITest automation testing.

    Register a single block (in the application under test) that will be invoked when an XCUITest automation test case has sent a message using the APLAutomationSendMessage() function. The -[APLConfiguration allowInvalidSignatures] method in the application under test must return YES for the message to be processed. See also APLAutomationSendMessage().

    Objective-C example

    APLAutomationMessageReceivedBlock(^NSObject* (NSString* name, id data) {
      if ([name isEqualToString: @"SetResponseData"]) {
        [MockedHttpInterceptor setResponse: data];
      }
      return nil;
    });
    

    Swift example

    APLAutomationMessageReceivedBlock { (name: String, data: Any) -> NSObject in
      if name == "SetResponseData" {
        MockedHttpInterceptor.setResponse(data)
      }
      return nil
    }
    

    Declaration

    Objective-C

    extern void APLAutomationMessageReceivedBlock(
        id _Nullable (^_Nullable message)(NSString *_Nonnull, id _Nullable))

    Swift

    func APLAutomationMessageReceivedBlock(_ message: ((String, Any?) -> Any?)?)
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    If logLevel is APLLogLevelDebug and logging is enabled (see also APLSetLogging()) then logs msg with optional parameters to the console. If logLevel is APLLogLevelError then logs msg with optional parameters to the console even if logging is disabled. You should prefer to use APLDEBUG or APLERROR macros for Objective-C. See also APLLogS() for Swift.

    Declaration

    Objective-C

    extern void APLLog(APLLogLevel logLevel, NSString *_Nonnull msg, ...)
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    If logLevel is .debug and logging is enabled (see also APLSetLogging) then logs msg to the console. If logLevel is .error then logs msg the console even if logging is disabled. See also APLLog for Objective-C.

    Declaration

    Objective-C

    extern void APLLogS(APLLogLevel logLevel, NSString *_Nonnull msg)

    Swift

    func APLLogS(_ logLevel: APLLogLevel, _ msg: String)
  • Target availability: iOS apps, iOS app extensions, watchOS apps, watchOS app extensions.

    When YES, Appfigurate library debugging messages will be output to the console. The default is NO. It is best practice to distribute applications via TestFlight and the App Store with logging set to NO. Also see APLLogging key in the Info.plist file.

    Declaration

    Objective-C

    extern void APLSetLogging(BOOL logging)

    Swift

    func APLSetLogging(_ logging: Bool)