AppRemoteConfig for iOS

远程配置应用:一种简单但有效的方式来远程管理应用。

创建一个简单易于维护和托管的配置文件,同时提供重要的灵活性,可以根据您的需求指定设置。

关于 AppRemoteConfig 的通用信息可以在这里找到。

Schema(架构)

JSON/YAML 架构定义在这里

CLI 实用工具

使用 care CLI 实用工具来初始化、验证、解析和准备配置文件。

要安装,请使用

brew install egeniq/app-utilities/care

多平台

Swift

在您的 Package.swift 文件中导入该包

.package(url: "https://github.com/egeniq/app-remote-config-ios", from: "0.5.0"),

然后,一个好的方法是创建您自己的 AppRemoteConfigClient

// App Remote Config
.target(
    name: "AppRemoteConfigClient",
    dependencies: [
        .product(name: "AppRemoteConfigService", package: "app-remote-config-ios"),
        .product(name: "AppRemoteConfigServiceMacros", package: "app-remote-config-ios"),
        .product(name: "Dependencies", package: "swift-dependencies"),
        .product(name: "DependenciesAdditions", package: "swift-dependencies-additions"),
        .product(name: "DependenciesMacros", package: "swift-dependencies"),
        .product(name: "Perception", package: "swift-perception")
    ]
)

使用这些依赖项

.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.0.0"),
.package(url: "https://github.com/pointfreeco/swift-perception", from: "1.0.0"),
.package(url: "https://github.com/tgrapperon/swift-dependencies-additions", from: "1.0.0")

然后您的 AppRemoteConfigClient.swift 看起来像这样

import AppRemoteConfigService
import AppRemoteConfigServiceMacros
import Dependencies
import DependenciesMacros
import Foundation
import Perception

@AppRemoteConfigValues @Perceptible @MainActor
public class Values {
    public private(set) var updateRecommended: Bool = false
    public private(set) var updateRequired: Bool = false
}

@DependencyClient
public struct AppRemoteConfigClient: Sendable {
    public var values: @Sendable @MainActor () -> Values = { Values() }
}

extension DependencyValues {
    public var configClient: AppRemoteConfigClient {
        get { self[AppRemoteConfigClient.self] }
        set { self[AppRemoteConfigClient.self] = newValue }
    }
}

extension AppRemoteConfigClient: TestDependencyKey {
    public static let testValue = Self()
}

extension AppRemoteConfigClient: DependencyKey {
    public static let liveValue = {
        let live = LockIsolated<LiveMainActorAppRemoteConfigClient?>(nil)
        return AppRemoteConfigClient(
            values: {
                if live.value == nil {
                    let dependency = LiveMainActorAppRemoteConfigClient()
                    live.setValue(dependency)
                }
                return live.value!.values
            }
        )
    }()
}

// This is used to workaround the error:
// Main actor-isolated static property 'liveValue' cannot be used to satisfy nonisolated protocol requirement.
@MainActor
private class LiveMainActorAppRemoteConfigClient {
    fileprivate let values: Values
    private let service: AppRemoteConfigService
    
    init() {
        let url = URL(string: "https://www.example.com/config.json")!
        let bundledConfigURL = Bundle.main.url(forResource: "appconfig", withExtension: "json")
        values = Values()
        service = AppRemoteConfigService(url: url, publicKey: nil, bundledConfigURL: bundledConfigURL, bundleIdentifier: Bundle.main.bundleIdentifier ?? "Sample", apply: values.apply(settings:))
    }
}

Android

对 Android 的支持可以在这里找到。