mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-09 22:35:56 +05:45
* Reuse custom variable values for checkpoints * Test custom variable Foundation bridging * Restore custom variable availability * Remove unused checkpoint integer value * Test checkpoint custom variable API syntax * Make custom variable conversion exhaustive * Update baseline swiftinterface files (#7411) --------- Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
165 lines
4.9 KiB
Swift
165 lines
4.9 KiB
Swift
//
|
|
// Copyright RevenueCat Inc. All Rights Reserved.
|
|
//
|
|
// Licensed under the MIT License (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://opensource.org/licenses/MIT
|
|
//
|
|
// Checkpoints.swift
|
|
//
|
|
// Created by Rick van der Linden.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// A custom value supplied when a checkpoint is hit.
|
|
///
|
|
/// This is a closed set because checkpoint properties support JSON primitive values only. Unlike checkpoint results,
|
|
/// adding arbitrary result variants is not part of this type's extensibility contract.
|
|
@_spi(Internal)
|
|
public enum CheckpointValue: Equatable, Hashable, Sendable {
|
|
|
|
// swiftlint:disable missing_docs
|
|
case string(String)
|
|
case double(Double)
|
|
case boolean(Bool)
|
|
// swiftlint:enable missing_docs
|
|
|
|
}
|
|
|
|
extension CheckpointValue: ExpressibleByStringLiteral {
|
|
|
|
/// Creates a string checkpoint value from a string literal.
|
|
public init(stringLiteral value: String) { self = .string(value) }
|
|
|
|
}
|
|
|
|
extension CheckpointValue: ExpressibleByIntegerLiteral {
|
|
|
|
/// Creates a numeric checkpoint value from an integer literal.
|
|
public init(integerLiteral value: Int64) { self = .double(Double(value)) }
|
|
|
|
}
|
|
|
|
extension CheckpointValue: ExpressibleByFloatLiteral {
|
|
|
|
/// Creates a floating-point checkpoint value from a floating-point literal.
|
|
public init(floatLiteral value: Double) { self = .double(value) }
|
|
|
|
}
|
|
|
|
extension CheckpointValue: ExpressibleByBooleanLiteral {
|
|
|
|
/// Creates a Boolean checkpoint value from a Boolean literal.
|
|
public init(booleanLiteral value: Bool) { self = .boolean(value) }
|
|
|
|
}
|
|
|
|
extension CheckpointValue: Codable {
|
|
|
|
/// Creates a checkpoint value by decoding a primitive JSON value.
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.singleValueContainer()
|
|
|
|
if let value = try? container.decode(String.self) {
|
|
self = .string(value)
|
|
} else if let value = try? container.decode(Bool.self) {
|
|
self = .boolean(value)
|
|
} else if let value = try? container.decode(Double.self) {
|
|
self = .double(value)
|
|
} else {
|
|
throw DecodingError.typeMismatch(
|
|
Self.self,
|
|
.init(
|
|
codingPath: decoder.codingPath,
|
|
debugDescription: "Expected a string, number, or boolean."
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Encodes the checkpoint value as a primitive JSON value.
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.singleValueContainer()
|
|
|
|
switch self {
|
|
case let .string(value): try container.encode(value)
|
|
case let .double(value): try container.encode(value)
|
|
case let .boolean(value): try container.encode(value)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension CheckpointValue {
|
|
|
|
/// Creates a checkpoint value from a supported Foundation primitive.
|
|
public init?(foundationValue: Any) {
|
|
if let value = foundationValue as? String {
|
|
self = .string(value)
|
|
return
|
|
}
|
|
|
|
guard let number = foundationValue as? NSNumber else { return nil }
|
|
switch number.jsonNumberKind {
|
|
case .boolean:
|
|
self = .boolean(number.boolValue)
|
|
case .integer, .floatingPoint:
|
|
self = .double(number.doubleValue)
|
|
}
|
|
}
|
|
|
|
/// The equivalent Foundation primitive value.
|
|
public var foundationValue: Any {
|
|
switch self {
|
|
case let .string(value): return value
|
|
case let .double(value): return NSNumber(value: value)
|
|
case let .boolean(value): return NSNumber(value: value)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension CheckpointValue {
|
|
|
|
var dimensionValue: DimensionValue {
|
|
switch self {
|
|
case let .string(value): return .string(value)
|
|
case let .double(value): return .double(value)
|
|
case let .boolean(value): return .bool(value)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// Per-call parameters for a checkpoint.
|
|
@_spi(Internal)
|
|
public final class CheckpointParams: Equatable, Hashable, CustomStringConvertible, @unchecked Sendable {
|
|
|
|
/// Custom variables usable in checkpoint targeting rules and feature events.
|
|
public let customVariables: [String: CheckpointValue]
|
|
|
|
/// Creates checkpoint parameters with the supplied custom variables.
|
|
public init(customVariables: [String: CheckpointValue] = [:]) {
|
|
self.customVariables = customVariables
|
|
}
|
|
|
|
/// Returns whether two parameter collections contain the same custom variables.
|
|
public static func == (lhs: CheckpointParams, rhs: CheckpointParams) -> Bool {
|
|
return lhs.customVariables == rhs.customVariables
|
|
}
|
|
|
|
/// Hashes the checkpoint parameters.
|
|
public func hash(into hasher: inout Hasher) {
|
|
hasher.combine(self.customVariables)
|
|
}
|
|
|
|
/// A debug description of the checkpoint parameters.
|
|
public var description: String {
|
|
return "CheckpointParams(customVariables=\(self.customVariables))"
|
|
}
|
|
|
|
}
|