JustTWeak es un marco de marcas de características para aplicaciones iOS. Proporciona una interfaz de fachada simple que interactúa con múltiples proveedores de ajuste que se consultan respetando una prioridad dada. Los ajustes representan las banderas utilizadas para impulsar las decisiones en el código del cliente.
Con JustTweak puede lograr lo siguiente:
JustTweak está disponible a través de Cocoapods. Para instalarlo, simplemente agregue la siguiente línea a su Podfile:
pod "JustTweak"
JustTWeak también está disponible a través de SPM. Copie la URL para este repositorio y agregue el paquete en la configuración de su proyecto.
LocalTweakProvider
que incluye sus funciones. Consulte LocalTweaks_example.json
para un punto de partida.Para configurar la pila, tiene dos opciones:
static let tweakManager : TweakManager = {
var tweakProviders : [ TweakProvider ] = [ ]
// Mutable TweakProvider (to override tweaks from other TweakProviders)
let userDefaultsTweakProvider = UserDefaultsTweakProvider ( userDefaults : UserDefaults . standard )
tweakProviders . append ( userDefaultsTweakProvider )
// Optimizely (remote TweakProvider)
let optimizelyTweakProvider = OptimizelyTweakProvider ( )
optimizelyTweakProvider . userId = UUID ( ) . uuidString
tweakProviders . append ( optimizelyTweakProvider )
// Firebase Remote Config (remote TweakProvider)
let firebaseTweakProvider = FirebaseTweakProvider ( )
tweakProviders . append ( firebaseTweakProvider )
// Local JSON-based TweakProvider (default TweakProvider)
let jsonFileURL = Bundle . main . url ( forResource : " LocalTweaks_example " , withExtension : " json " ) !
let localTweakProvider = LocalTweakProvider ( jsonURL : jsonFileURL )
tweakProviders . append ( localTweakProvider )
return TweakManager ( tweakProviders : tweakProviders )
} ( )
LocalTweakProvider
. Consulte TweakAccessor.swift
para un punto de partida. config.json
en el siguiente formato: {
"accessorName" : " GeneratedTweakAccessor "
}
El único valor compatible actualmente es accessorName
que define el nombre de la clase generada.
Podfile
script_phase :name = > ' TweakAccessorGenerator ' ,
:script = > ' $SRCROOT/../TweakAccessorGenerator
-l $SRCROOT/<path_to_the_local_tweaks_json_file>
-o $SRCROOT/<path_to_the_output_folder_for_the_generated_code>
-c $SRCROOT/<path_to_the_folder_containing_config.json> ' ,
:execution_position = > :before_compile
Cada vez que se construye el objetivo, la herramienta Generador de código regenerará el código para la pila. Incluirá todas las propiedades que respaldan las características definidas en LocalTweakProvider
.
Si ha utilizado la herramienta Generador de código, la pila generada incluye todos los indicadores de características. Simplemente asigne el objeto del accesor (cuyo nombre ha definido en la configuración .json
y úselo para acceder a los indicadores de características.
let accessor = GeneratedTweakAccessor ( with : < #tweak_manager_instance# > )
if accessor . meaningOfLife == 42 {
...
}
Ver GeneratedTweakAccessor.swift
y GeneratedTweakAccessor+Constants.swift
para un ejemplo de código generado.
Si decidió implementar el código de pila usted mismo, tendrá que implementar el código para acceder a las características a través del TweakManager
.
Se puede acceder a las tres características principales de JustTWeak desde la instancia TweakManager
para impulsar las decisiones de la ruta del código.
// check for a feature to be enabled
let enabled = tweakManager . isFeatureEnabled ( " some_feature " )
if enabled {
// enable the feature
} else {
// default behaviour
}
TweakManager
le devolverá el valor del proveedor de ajuste con la más alta prioridad y automáticamente retroceso a los demás si no se encuentra ningún valor establecido. Lanza la ejecución cuando se encuentra un ajuste nulo que se puede atrapar y manejar según sea necesario. Use tweakWith(feature:variable:)
o los envoltorios de propiedades proporcionados.
// check for a tweak value
let tweak = try ? tweakManager . tweakWith ( feature : " some_feature " , variable : " some_flag " )
if let tweak = tweak {
// tweak was found in some tweak provider, use tweak.value
} else {
// tweak was not found in any tweak provider
}
O con hacer capturas
// check for a tweak value
do {
let tweak = try tweakManager . tweakWith ( feature : " some_feature " , variable : " some_flag " )
// tweak was found in some tweak provider, use tweak.value
return tweak
} catch let error as TweakError {
switch error {
case . notFound : ( ) // "Feature or variable is not found"
case . notSupported : ( ) // "Variable type is not supported"
case . decryptionClosureNotProvided : ( ) // "Value is encrypted but there's no decryption closure provided"
}
} catch let error { // add a default catch to satisfy the compiler
print ( error . localizedDescription )
}
@TweakProperty
, @OptionalTweakProperty
y @FallbackTweakProperty
Wrappers están disponibles para marcar las propiedades que representan banderas de características. Tenga en cuenta que para usar estos envoltorios de propiedades, se necesita una instancia estática de TweakManager
.
@ TweakProperty ( feature : < #feature_key# > ,
variable : < # var iable_key# > ,
tweakManager : < #TweakManager# > )
var labelText : String
@ OptionalTweakProperty ( fallbackValue : < #nillable_fallback_value# > ,
feature : < #feature_key# > ,
variable : < # var iable_key# > ,
tweakManager : < #TweakManager# > )
var meaningOfLife : Int ?
@ FallbackTweakProperty ( fallbackValue : < #nillable_fallback_value# > ,
feature : < #feature_key# > ,
variable : < # var iable_key# > ,
tweakManager : < #TweakManager# > )
var shouldShowFeatureX : Bool
El orden de los objetos en la matriz tweakProviders
define la prioridad de los proveedores de ajustes.
El MutableTweakProvider
con la más alta prioridad, como UserDefaultsTweakProvider
en el ejemplo anterior, se utilizará para reflejar los cambios realizados en la UI ( TweakViewController
). LocalTweakProvider
debe tener la prioridad más baja, ya que proporciona los valores predeterminados de un proveedor de ajuste local y es el utilizado por el TweakViewController
para llenar la interfaz de usuario.
Para migrar de manual a la implementación generada por el código, es necesario actualizar el nuevo formato .json
. Para ayudar con este proceso, hemos agregado la propiedad GeneratedPropertyName
al objeto de ajuste. Establezca este valor para alinearse con los nombres de sus propiedades actuales en el código, de modo que las propiedades de accesorios generadas coincidan con su implementación existente.
El TweakManager
proporciona la opción de almacenar en caché los valores de ajuste para mejorar el rendimiento. El almacenamiento en caché está deshabilitado de forma predeterminada, pero se puede habilitar a través de la propiedad useCache
. Cuando está habilitado, hay dos formas de restablecer el caché:
resetCache
en el TweakManager
TweakProviderDidChangeNotification
JustTWeak viene con un ViewController que permite al usuario editar MutableTweakProvider
con la más alta prioridad.
func presentTweakViewController ( ) {
let tweakViewController = TweakViewController ( style : . grouped , tweakManager : < #TweakManager# > )
// either present it modally
let tweaksNavigationController = UINavigationController ( rootViewController : tweakViewController )
tweaksNavigationController . navigationBar . prefersLargeTitles = true
present ( tweaksNavigationController , animated : true , completion : nil )
// or push it on an existing UINavigationController
navigationController ? . pushViewController ( tweakViewController , animated : true )
}
Cuando se modifica un valor en cualquier MutableTweakProvider
, se dispara una notificación para dar a los clientes la oportunidad de reaccionar y reflejar cambios en la interfaz de usuario.
override func viewDidLoad ( ) {
super . viewDidLoad ( )
NotificationCenter . defaultCenter ( ) . addObserver ( self ,
selector : #selector ( updateUI ) ,
name : TweakProviderDidChangeNotification ,
object : nil )
}
@ objc func updateUI ( ) {
// update the UI accordingly
}
JustTweak viene con tres proveedores de ajuste fuera de la caja:
UserDefaultsTweakProvider
, que es mutable y utiliza UserDefaults
como un almacén de clave/valorLocalTweakProvider
, que es de solo lectura y utiliza un archivo JSON que está destinado a mantener la configuración de marcado de características predeterminadaEphemeralTweakProvider
, que es simplemente una instancia de NSMutableDictionary
Además, JustTWeak define los protocolos TweakProvider
y MutableTweakProvider
que puede implementar para crear su propio proveedor de ajuste para satisfacer sus necesidades. En el proyecto de ejemplo, puede encontrar algunos ejemplos que puede usar como punto de partida.
JustTWeak ofrece la capacidad de agregar una decryptionClosure
a un TweakProvider
. Este cierre toma el Tweak
como entrada y devuelve un TweakValue
como salida. El cierre le permite hacer un preprocesamiento en su ajuste que puede usarse para descifrar los valores. Esto se puede usar si tiene un valor cifrado en su archivo JSON de ajustes como se puede ver a continuación:
"encrypted_answer_to_the_universe" : {
"Title" : " Encrypted definitive answer " ,
"Description" : " Encrypted answer to the Ultimate Question of Life, the Universe, and Everything " ,
"Group" : " General " ,
"Value" : " 24 ton yletinifeD " ,
"GeneratedPropertyName" : " definitiveAnswerEncrypted " ,
"Encrypted" : true
}
Tenga en cuenta que debe especificar si el valor está encriptado en su archivo JSON (con la propiedad Encrypted
) para el cierre de descifrado para procesar el valor. El cierre de descifrado para el JSON anterior se puede especificar de la siguiente manera:
tweakProvider . decryptionClosure = { tweak in
// decrypt `tweak.value` with your cypher of choice and return the decrypted value
}
De esta manera, el ajuste obtenido del proveedor de ajustes tendrá el valor descifrado.
JustTWeak está disponible bajo la licencia Apache 2.0. Consulte el archivo de licencia para obtener más información.