AppRemoteConfig

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

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

Schema (模式)

JSON/YAML 模式定义在此处

AppRemoteConfigClient

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

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

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

// App Remote Config
.target(
    name: "AppRemoteConfigClient",
    dependencies: [
        .product(name: "AppRemoteConfigService", package: "app-remote-config"),
        .product(name: "AppRemoteConfigServiceMacros", package: "app-remote-config"),
        .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:))
    }
}

CLI 实用程序

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

要安装,请使用

brew install egeniq/app-utilities/care

用法

“care”命令行实用程序具有内置的帮助文档。

care --help

有五个子命令可以使用:init、create-key-pair、verify、resolve 和 prepare。

Init (初始化)

创建一个新的配置文件

care init appconfig.yaml

这将创建一个新文件

# yaml-language-server: $schema=https://raw.githubusercontent.com/egeniq/app-remote-config/main/Schema/appremoteconfig.schema.json
$schema: https://raw.githubusercontent.com/egeniq/app-remote-config/main/Schema/appremoteconfig.schema.json

# Settings for the current app.
settings:
  foo: 42
  coolFeature: false

# Keep track of keys that are no longer in use.
deprecatedKeys:
- bar

# Override settings
overrides:
- matching:
  # If any of the following combinations match
  - appVersion: <=0.9.0
    platform: Android
  - appVersion: <1.0.0
    platform: iOS
  - platformVersion: <15.0.0
    platform: iOS.iPad
  # These settings get overriden.
  settings:
    bar: low
 
# Or release a new feature at a specific time
- schedule:
    from: '2024-12-31T00:00:00Z'
  settings:
    coolFeature: true
    
# Store metadata here
meta:
  author: Your Name

settings 键下,您将放置您希望在您的应用程序中使用的当前设置。 如果任何键已弃用,请将它们添加到 deprecatedKeys 数组中,以便它们仍然可以被覆盖。

overrides 中,您可以定义因多种因素而异的设置,例如 appVersion、platform、platformVersion。 有关选项的完整列表,请参阅帮助文档。 如果其中一个组合匹配,则设置将覆盖来自根 settings 键的设置。 设置从上到下应用。

您还可以安排设置中的更改。 如果您添加带有 from 和/或 until ISO8601 日期格式的 schedule,则只有当当前时间位于该范围内时才会应用设置。 省略 from 意味着使用遥远的过去,省略 to 意味着使用遥远的将来。

meta 下的键不使用,但仅用于跟踪元数据。

Create Key Pair (创建密钥对)

您的应用程序可以使用公钥来确保该配置已使用您的私钥签名。 对配置进行签名是可选的。

care create-key-pair

Verify (验证)

如果您的编辑器支持,JSON 模式可以帮助您正确格式化配置文件。 您可以通过运行以下命令进一步验证配置文件的正确性

care verify appconfig.yaml

Resolve (解析)

要检查您设置的设置和覆盖是否正确,您可以要求 care 显示设置将如何解析。

care resolve appconfig.yaml -p iOS --platform-version 16  -v 1.0.1

这将显示类似以下内容

Resolving for:
  platform            : iOS
  platform version    : 16.0.0
  app version         : 1.0.1
  build variant       : release

Settings on 2024-02-22 11:40:00 +0000:
  coolFeature         : false
  foo                 : 42

Settings on 2024-12-31 00:00:00 +0000:
  coolFeature         : false -> true
  foo                 : 42

No further overrides scheduled.

Prepare (准备)

最后一步是将配置文件转换为紧凑的 json。

care prepare appconfig.yaml appconfig.json

现在,文件 appconfig.json 就可以通过 Web 服务器提供给您的应用程序了。

Android

此软件包可以在 Android 上编译,但也有一个可用的 Kotlin 端口在此处