JustTWeak ist ein Feature -Feature -Framework für iOS -Apps. Es bietet eine einfache Fassadenschnittstelle, die mit mehreren Tweak -Anbietern interagiert, die eine bestimmte Priorität respektieren. Optimierungen stellen Flags dar, die verwendet werden, um Entscheidungen im Client -Code zu fördern.
Mit JustTWeak können Sie Folgendes erreichen:
JustTWeak ist über Cocoapods erhältlich. Um es zu installieren, fügen Sie einfach die folgende Zeile zu Ihrem Podfile hinzu:
pod "JustTweak"
JustTWeak ist auch über SPM erhältlich. Kopieren Sie die URL für dieses Repo und fügen Sie das Paket in Ihre Projekteinstellungen hinzu.
LocalTweakProvider
-JSON -Datei mit Ihren Funktionen. Informationen zu einem Ausgangspunkt finden Sie in LocalTweaks_example.json
.Um den Stack zu konfigurieren, haben Sie zwei Optionen:
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
unterstützt werden. Siehe TweakAccessor.swift
für einen Ausgangspunkt. config.json
-Datei im folgenden Format: {
"accessorName" : " GeneratedTweakAccessor "
}
Der einzige derzeit unterstützte Wert ist accessorName
, der den Namen der generierten Klasse definiert.
Podfile
Folgendes hinzu 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
Jedes Mal, wenn das Ziel erstellt wird, wird das Codegenerator -Tool den Code für den Stapel regeneriert. Es wird alle Eigenschaften enthalten, die die im LocalTweakProvider
definierten Funktionen unterstützen.
Wenn Sie das Codegenerator -Tool verwendet haben, enthält der generierte Stapel alle Funktionsflags. Zuleiten Sie einfach das Accessor -Objekt (welcher Name, den Sie in der .json
-Konfiguration definiert haben, und greifen Sie mit es auf die Feature -Flags zu.
let accessor = GeneratedTweakAccessor ( with : < #tweak_manager_instance# > )
if accessor . meaningOfLife == 42 {
...
}
Siehe GeneratedTweakAccessor.swift
und GeneratedTweakAccessor+Constants.swift
für ein Beispiel für generierten Code.
Wenn Sie beschlossen haben, den Stack -Code selbst zu implementieren, müssen Sie Code implementieren, um über den TweakManager
auf die Funktionen zuzugreifen.
Die drei Hauptmerkmale von JustTWeak können von der TweakManager
-Instanz zugegriffen werden, um Codepfadentscheidungen voranzutreiben.
// check for a feature to be enabled
let enabled = tweakManager . isFeatureEnabled ( " some_feature " )
if enabled {
// enable the feature
} else {
// default behaviour
}
TweakManager
wird den Wert vom Tweak -Anbieter mit höchster Priorität zurückgeben und automatisch auf die anderen zurückfallen, wenn kein festgelegter Wert gefunden wird. Es wirft die Führung, wenn ein Null -Tweak gefunden wird, der bei Bedarf gefangen und gehandhabt werden kann. Verwenden Sie entweder tweakWith(feature:variable:)
oder die bereitgestellten Eigenschaftenverpackungen.
// 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
}
Oder mit dem Startcharakter
// 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
und @FallbackTweakProperty
-Immobilienverpackungen sind zur Markierung von Eigenschaften zur Darstellung von Feature -Flags verfügbar. Denken Sie daran, dass es erforderlich ist, um diese Eigenschaftsverpackungen zu verwenden, um eine statische Instanz von TweakManager
zu verwenden.
@ 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
Die Reihenfolge der Objekte im tweakProviders
-Array definiert die Priorität der Tweak -Anbieter.
Der MutableTweakProvider
mit der TweakViewController
Priorität, wie UserDefaultsTweakProvider
. Der LocalTweakProvider
sollte die niedrigste Priorität haben, da er die Standardwerte eines lokalen Tweak -Anbieters liefert und der von dem TweakViewController
verwendet wird, um die Benutzeroberfläche zu bevölkern.
Um von manuell zu dem mit Code generierten Implementierung zu migrieren, muss das neue .json
-Format aktualisiert werden. Um diesen Prozess zu unterstützen, haben wir das Tweak -Objekt die Eigenschaft GeneratedPropertyName
hinzugefügt. Legen Sie diesen Wert so ein, dass Sie Ihren aktuellen Eigenschaftsnamen im Code anpassen, damit die generierten Accessor -Eigenschaften mit Ihrer vorhandenen Implementierung übereinstimmen.
Der TweakManager
bietet die Option, die Optimierungswerte zu zwischenstrahlen, um die Leistung zu verbessern. Das Caching ist standardmäßig deaktiviert, kann jedoch über die useCache
-Eigenschaft aktiviert werden. Wenn es aktiviert ist, gibt es zwei Möglichkeiten, den Cache zurückzusetzen:
resetCache
-Methode auf dem TweakManager
anTweakProviderDidChangeNotification
-Benachrichtigung ab JustTWeak verfügt über einen ViewController, mit dem der Benutzer den MutableTweakProvider
mit höchster Priorität bearbeiten kann.
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 )
}
Wenn in einem MutableTweakProvider
ein Wert modifiziert wird, wird eine Benachrichtigung abgefeuert, um den Kunden die Möglichkeit zu geben, zu reagieren und Änderungen in der Benutzeroberfläche zu reflektieren.
override func viewDidLoad ( ) {
super . viewDidLoad ( )
NotificationCenter . defaultCenter ( ) . addObserver ( self ,
selector : #selector ( updateUI ) ,
name : TweakProviderDidChangeNotification ,
object : nil )
}
@ objc func updateUI ( ) {
// update the UI accordingly
}
JustTWeak verfügt über drei Tweak-Anbieter außerhalb des Boxs:
UserDefaultsTweakProvider
, der veränderlich ist und UserDefaults
als Schlüssel-/Wertspeicher verwendetLocalTweakProvider
, der schreibgeschützt ist und eine JSON-Datei verwendet, die das Standard-Feature-Feature-Setup aufbewahrt hatEphemeralTweakProvider
, das einfach eine Instanz von NSMutableDictionary
ist Darüber hinaus definiert JustTWeak TweakProvider
und MutableTweakProvider
-Protokolle, die Sie implementieren können, um Ihren eigenen Tweak -Anbieter für Ihre Anforderungen zu erstellen. Im Beispielprojekt finden Sie einige Beispiele, die Sie als Ausgangspunkt verwenden können.
JustTWeak bietet die Möglichkeit, einem TweakProvider
eine decryptionClosure
zu verleihen. Dieser Verschluss nimmt den Tweak
als Eingabe an und gibt einen TweakValue
als Ausgang zurück. Mit dem Verschluss können Sie eine Vorverarbeitung auf Ihrem Tweak durchführen, mit dem z. B. zum Entschlüsseln von Werten verwendet werden kann. Dies kann verwendet werden, wenn Sie einen verschlüsselten Wert in Ihrer Tweaks -JSON -Datei haben, wie unten zu sehen ist:
"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
}
Beachten Sie, dass Sie angeben müssen, ob der Wert in Ihrer JSON -Datei (mit der Encrypted
Eigenschaft) für die Entschlüsselungsschließung verschlüsselt ist, um den Wert zu verarbeiten. Die Entschlüsselungsschließung für den obigen JSON kann wie folgt angegeben werden:
tweakProvider . decryptionClosure = { tweak in
// decrypt `tweak.value` with your cypher of choice and return the decrypted value
}
Auf diese Weise wird der vom Tweak -Anbieter abgerufene Verbesserung den entschlüsselten Wert haben.
JustTWeak ist unter der Apache 2.0 -Lizenz verfügbar. Weitere Informationen finden Sie in der Lizenzdatei.