Shiply iOS Remote Config SDK Integration
1. Access Guide
Prerequisites: Please read before accessinggeneral concepts to learn about the common
appId/appKey/guid/qimei/envId/updateMode/systemId/Dependency injection and other core concepts to avoid cross-platform confusion.
1.1 Create RDelivery instance
If you encounter iOS SDK Pod Install failure, please update the version number:
- ShiplyPro >= 1.1.0
- ShiplyResHub >= 1.10.22-rc.5
- ShiplyRDelivery >= 1.3.6.9
You can refer to the Demo project (Public Warehouse) to experience and access.
RDelivery Supports multiple instances, you can use a singleton to hold an RDelivery instance andapplication:didFinishLaunchingWithOptions:Initialization is done in the method. Minimal setup
#import <UIKit/UIDevice.h>
#import <ShiplyRDelivery/RDeliveryJsonModelImpl.h>
#import <ShiplyRDelivery/RDNetworkImpl.h>
#import <ShiplyRDelivery/RDLoggerImpl.h>
#import <ShiplyRDelivery/RDMMKVFactoryImpl.h>
// The SDK supports dependency injection for network, logging, storage, and other components. Use these default implementations.
RDeliveryDepends *depends = [RDeliveryDepends new]; // Initialize dependency injection
depends.httpImpl = [RDNetworkImpl sharedInstance]; // Inject network implementation
depends.logImpl = [RDLoggerImpl sharedInstance]; // Inject logging implementation; RDLoggerImpl uses NSLog by default—inject your own logger in production
depends.kvImpl = [RDMMKVFactoryImpl sharedInstance]; // Inject storage implementation
depends.jsonModelImpl = [RDeliveryJsonModelImpl sharedInstance];
// Initialize SDK settings
RDeliverySDKSettings *setting = [RDeliverySDKSettings settingWithAppId:kRDeliveryDemoAppid // appId from your Shiply web project
appKey:kRDeliveryDemoAppkey // appKey from your Shiply web project
guid:kRDeliveryDemoGuid1 // Your user ID for number-package rule matching
depends:depends];
// Device identifier (your unique device ID)
setting.qimei = kRDeliveryDemoQimei;
// Environment ID (production by default; optional)
setting.envId = RDeliveryReleaseEnvId;
// Set automatic config update strategy (default: no automatic updates)
setting.updateMode = RDCONFIG_UPDATE_MODE_APP_START | // Update on startup
RDCONFIG_UPDATE_MODE_SCHEDUAL | // Scheduled update
RDCONFIG_UPDATE_MODE_NETWORK_CHANGE; // Update when network becomes available
setting.systemVersion = [UIDevice currentDevice].systemVersion; // System version
self.rdeliverySDK = [RDeliverySDK createSDKWithSettings:setting];
1.2 Component dependency injection and replacement
RDelivery SDK Supports dependency injection of key components, and provides default network (depends on NSURLSession), storage (depends on MMKV), and logging (depends on NSLog) components. The access party can inject components with custom functions into the SDK for use by implementing relevant component protocols.
Network protocol (RAFTNetworkProtocol)
Storage protocols (RAFTKVStorageProtocol, RAFTKVStorageFactoryProtocol)
Logging protocol (RAFTLogProtocol)
JSON model conversion protocol (RDeliveryYYModelProtocol) Common scenarios that require custom dependency injection components:
Print RDelivery SDK logs
RDelivery uses YYModel as the JSON conversion tool, but the access party wants to use other JSON libraries
The access party uses a modified version of MMKV or YYModel and other libraries, causing dependency conflicts when accessing RDelivery.
The accessing party initializes initializeMMKV globally in the App and does not want to call initializeMMKV synchronously again when RDelivery is initialized. How to replace components? Taking the replacement of jsonModelImpl as an example, you can copy the .h and .m files of RDeliveryJsonModelImpl, modify the class name XXXJsonModelImpl, and then implement the modelToJSONData: and modelWithJSON:classType methods of the RDeliveryYYModelProtocol protocol.
- (nullable NSData *)modelToJSONData:(nonnull id)object {
return [object yy_modelToJSONData];
}
- (nonnull id)modelWithJSON:(nonnull NSString *)json classType:(nonnull Class)cls {
return [cls yy_modelWithJSON:json];
}
Finally, the XXXJsonModelImpl singleton is injected to complete dependency replacement.
RDeliveryDepends *depends = [RDeliveryDepends new];
depends.jsonModelImpl = [XXXJsonModelImpl sharedInstance]; // Inject default JSON model conversion implementation
1.3 Print SDK log (important)
In order to facilitate problem location, it is recommended that the business side inject the business-customized log implementation when creating an RDelivery instance so that the online version can output RDelivery logs. For details, please refer to the implementation of RDLoggerImpl and change the NSLog part to use the business side's log component output.
RDeliveryDepends *depends = [RDeliveryDepends new];
depends.logImpl = [XXXLoggerImpl sharedInstance]; // Your custom logging dependency injection
1.4 Other optional settings
#import "sys/utsname.h"
// Set default update interval (default 4 hours). Takes effect only when update strategy includes RDCONFIG_UPDATE_MODE_SCHEDUAL
setting.updateDuration = 14400.0;
// Set custom attributes
setting.profiles = @{@"key": @"value",
@"age": @"25",
@"name":@"tom",
};
struct utsname systemInfo;
uname(&systemInfo);
NSString *deviceType = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
setting.deviceType = deviceType; // Device model
// If business code reads config during initialization, config may not be loaded yet. Implement RDConfigEventListener and read config in onConfigInfoInited
[self.rdeliverySDK addConfigEventListener:self];
2. Using configurations and switches
2.1 Default values of configuration switches
For configurations with defaultValue parameters, if the obtained configuration is empty, defaultValue will be returned as the default value;
For configurations without defaultValue parameters, if the obtained configuration is empty, the corresponding empty value will be returned (object returns nil, int returns 0, etc.)
2.2 Get configuration values
When the configuration switch key does not exist on the remote end, or the configuration is not pulled, or the configuration value of the key is not set on the web, defaultValue will be returned.
NSString *stringValue = [self.rdeliverySDK stringValueWithKey:configKey defaultValue:@"{\"k1\":\"v1\"}"];
2.3 Get switch value
When the configuration switch key does not exist on the remote end, or the configuration is not pulled, or the switch value of the key on the web is "not set", defaultValue will be returned.
BOOL isSwitchOn = [self.rdeliverySDK isSwitchOn:configKey defaultValue:NO];
2.4 Get the configuration object (RDConfigInfo type)
RDConfigInfo *info = [self.rdeliverySDK configInfoWithKey:configKey];
2.5 Manually pull RDelivery remote configuration switch
You can also manually call the interface to pull RDelivery remote configuration:
2.5.1 Pull full configuration
[self.rdeliverySDK updateConfigWithCompleteHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"Pull succeeded");
}
}];
2.5.2 Pull configuration by scene ID
[self.rdeliverySDK updateConfigWithSceneId:@"100080" completeHandler:^(NSArray<RDConfigInfo *> * _Nonnull configInfoArray, NSError * _Nullable error) {
if (!error) {
NSLog(@"Pull succeeded, config count: %lu", (unsigned long)configInfoArray.count);
}
}];
2.5.3 Pull a single configuration
[self.rdeliverySDK updateConfigWithKey:@"testA" completeHandler:^(RDConfigInfo * _Nonnull configInfo, NSError * _Nullable error) {
if (!error) {
NSLog(@"Pull succeeded, config value: %@", configInfo.stringValue);
}
}];
3. API introduction
- External interface: RDeliverySDK.h
- SDK initialization settings: RDeliverySDKSettings.h
- Configuration value update protocol: RDConfigInfoListener.h
- Configure startup loading and business reading protocol: RDConfigEventListener.h
RDConfigEventListener protocol
@protocol RDConfigEventListener <NSObject>
@optional
/// Called when the business reads a config key; set needReport=YES to let the SDK report automatically
- (void)onGetConfigInfoInvoked:(NSString *)key configInfo:(RDConfigInfo *)configInfo needReport:(BOOL *)needReport;
/// Called when a config value is updated
- (void)onConfigChanged:(NSString *)key;
/// Local cache initialization complete—config may not be ready at startup; read config in this callback
- (void)onConfigInfoInited;
/// Full pull request completed
- (void)onConfigRequestPullTypeAllFinished:(NSError *)error;
/// Full pull response processing completed
- (void)onConfigPullTypeAllProcessFinished:(NSError *)error;
/// Legacy TAB platform compatibility; not recommended
- (void)onConfigRequestFinished:(NSError *)error;
@end
RDConfigInfoListener protocol
@protocol RDConfigInfoListener <NSObject>
/// Called when the config for the specified key changes
- (void)onConfigInfoChanged:(NSString *)key;
@end
Thread Note: The RDelivery listener callback does not promise a callback on any specific thread, and cannot assume that the callback is on the main thread.
Event monitoring
// Add listeners
[self.rdeliverySDK addConfigEventListener:self]; // Implement RDConfigEventListener protocol
[self.rdeliverySDK addConfigInfoListener:self forKey:@"my_key"]; // Implement RDConfigInfoListener protocol
// Remove listeners
[self.rdeliverySDK removeConfigEventListener:self];
[self.rdeliverySDK removeConfigInfoListener:self forKey:@"my_key"];
4. Frequently Asked Questions and Notes
Update policy bitmask value
updateModeis a bitmask, Supports|Use in combination:
| constant | value | description |
|---|---|---|
RDCONFIG_UPDATE_MODE_NONE | 0 | No automatic updates |
RDCONFIG_UPDATE_MODE_APP_START | 1 (1<<0) | Pull on startup |
RDCONFIG_UPDATE_MODE_SCHEDUAL | 2 (1<<1) | Scheduled pull |
RDCONFIG_UPDATE_MODE_ENTER_FOREGROUND | 4 (1<<2) | Pull when switching to the front desk |
RDCONFIG_UPDATE_MODE_NETWORK_CHANGE | 8 (1<<3) | Pull when network recovers |
// Example: pull on startup + scheduled pull
setting.updateMode = RDCONFIG_UPDATE_MODE_APP_START | RDCONFIG_UPDATE_MODE_SCHEDUAL; // = 3
Notes
init/newUnavailable: requiredcreateSDKWithSettings:。- Private information needs to be injected:
systemVersion/deviceType/qimei/guidIt needs to be provided by the business party, and the SDK does not actively obtain it. - Configuration key is prohibited from containing dots
.: The platform does not have Supports, and will return error code 102104, which needs to be replaced with_And synchronize the client changes. - Multiple instances: Supports multiple instances, holding multiple RDeliverySDKs with different appIds.
- Log injection: The default NSLog implementation is not available online, so business logs must be injected.
RDeliverySDKSettings key properties
| Properties | Type | Description |
|---|---|---|
appId / appKey | NSString | Application credentials (required, readonly) |
guid | NSString | User ID (diversion) |
qimei | NSString | Device identification (reported) |
envId | NSString | Environment ID, defaultRDeliveryReleaseEnvId |
appVersion | NSString | App version |
systemVersion | NSString | System version (privacy compliance, needs to be injected) |
bundleId / deviceType | NSString | Package name/model (needs to be injected) |
updateMode | RDConfigUpdateMode | Update policy bitmask |
updateDuration | NSTimeInterval | Timing interval, default 4h, no less than 10min |
timeout | NSTimeInterval | Request timeout, default 15s |
profiles | NSDictionary | Custom attribute labels |
fixedAfterHitKeys | NSSet | key to lock the value after the first hit |
isDebugPackage | BOOL | debug package flag |
pullTarget | RDConfigServerPullTarget | Project-level/App-level pull, default project level |
Dependency injection protocol
passRDeliveryDependsinjection(RDeliveryDependProtocol.h):
| Properties | Protocol | Default Implementation |
|---|---|---|
httpImpl | RAFTNetworkProtocol | RDNetworkImpl (NSURLSession) |
logImpl | RAFTLogProtocol | RDLoggerImpl (NSLog) |
kvImpl | RAFTKVStorageFactoryProtocol | RDMMKVFactoryImpl (MMKV) |
jsonModelImpl | RDeliveryYYModelProtocol | RDeliveryJsonModelImpl (YYModel) |
Switch user/environment
Multiple accounts or different environment scenarios (common):
// Switch user—triggers storage isolation and re-matches gray rules (re-pull remote config manually)
[self.rdeliverySDK switchGuid:kNewUserGuid];
// Switch environment—production: RDeliveryReleaseEnvId; default test: RDeliveryTestEnvId
[self.rdeliverySDK switchEnvironment:RDeliveryTestEnvId];
After switching, the storage will be automatically switched and needs to be calledupdateConfigWithCompleteHandler:Re-pull the corresponding configuration.
Other APIs
| Method | Description |
|---|---|
+ (NSString *)sdkVersion | Get SDK version number (class method) |
- (BOOL)hasDataInitialized | Whether the local configuration has been loaded |
- (void)clearAllCache | Clear all caches (disk + memory) |
- (void)deleteDataWithKey: | Delete the configuration of the specified key (used in safe mode scenarios) |
FAQ
Configuration key reading returns nil / empty
- Confirm that SDK initialization is successful (
createSDKWithSettings:No error reported) - Check
hasDataInitializedWhether it is YES; if it is NO, you canonConfigInfoInitedRead in the callback, or usereadConfigInfoWithKeyFromDisk:Synchronous disk reading - Use
updateConfigWithCompleteHandler:Actively pull and then read - Check
envIdCorrect - the configuration may only exist in a specific environment
Unable to receive configuration change events
- Confirm that the listener has been registered:
addConfigEventListener:/addConfigInfoListener:forKey:Called before reading configuration - Confirm that the key name is exactly the same as the Shiply platform (including upper and lower case)
RDConfigEventListenerofonConfigChanged:It is only triggered when there are changes after the full pull; single key pull needs to be monitoredRDConfigInfoListener
The configuration value is not updated (old value is read)
- Check
updateModeWhether to include scheduled/foreground update strategy - If used
fixedAfterHitKeys, the key after being hit will not be updated before the App is restarted. - Manual call
updateConfigWithCompleteHandler:Force refresh
The configuration remains unchanged after switching users.
switchguidAfter the SDK automatically switches storage, it will not automatically pull the configuration of the new user. Need to be called manuallyupdateConfigWithCompleteHandler:Trigger full pull.
Documentation and implementation differences
- Version number: written in official documents
1.3.6.5, the podspec is actually 1.3.8. Subject to podspec. - The rest of the API signature in the document is consistent with the source code, with no major differences.