How YTLite Manages Preferences and Data Using YTLUserDefaults
YTLite stores all user settings in a dedicated NSUserDefaults suite named com.dvntm.ytlite, accessed through a singleton YTLUserDefaults class that provides macaque-wrapped getters, setters, and reset functionality.
The YTLite tweak for YouTube iOS manages every user-configurable feature—from ad blocking to playback speed—through a centralized preference system built on YTLUserDefaults. This lightweight subclass of NSUserDefaults ensures consistent state across the entire tweak while providing a clean API for both direct access and macro-based convenience.
What Is YTLUserDefaults?
YTLUserDefaults is a specialized subclass defined in Utils/YTLUserDefaults.h and implemented in Utils/YTLUserDefaults.m. Unlike standard NSUserDefaults, it scopes all operations to a specific suite name (com.dvntm.ytlite) and enforces a singleton pattern to prevent multiple instances from desynchronizing preferences.
The class serves three core functions: creating a thread-safe singleton, registering baseline defaults on first launch, and providing a complete reset mechanism.
The Singleton Pattern and Suite Initialization
The +standardUserDefaults class method in Utils/YTLUserDefaults.m (lines 7-13) implements a classic GCD-based singleton:
+ (YTLUserDefaults *)standardUserDefaults {
static YTLUserDefaults *defaults = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
defaults = [[self alloc] initWithSuiteName:kDefaultsSuiteName];
[defaults registerDefaults];
});
return defaults;
}
Key implementation details:
dispatch_onceguarantees exactly one initialization regardless of thread contentioninitWithSuiteName:creates an isolated preferences container that persists across app launchesregisterDefaultsimmediately populates the suite with baseline values
The suite name constant kDefaultsSuiteName is defined as @"com.dvntm.ytlite", ensuring YTLite's preferences don't conflict with YouTube's own settings or other tweaks.
Registering Baseline Configuration
The -registerDefaults method (lines 23-34 in Utils/YTLUserDefaults.m) establishes every toggle's initial state:
- (void)registerDefaults {
[self registerDefaults:@{
@"noAds": @YES,
@"backgroundPlayback": @YES,
// ... additional default keys
}];
}
This baseline dictionary is critical for YTLite's behavior: it ensures that every feature has a defined value even before the user opens Settings for the first time. The NSUserDefaults -registerDefaults: method is non-destructive—it only sets values for keys that don't already exist, preserving any user changes across updates.
The Macro Façade for Daily Use
While direct YTLUserDefaults access works, YTLite's codebase primarily uses convenience macros defined in YTLite.h (lines 11-15). These macros provide terse, type-safe access to preferences throughout the tweak:
| Macro | Purpose | Example Usage |
|---|---|---|
ytlBool(key) |
Read BOOL value |
if (ytlBool(@"noAds")) { ... } |
ytlInt(key) |
Read NSInteger value |
NSInteger speed = ytlInt(@"speedIndex"); |
ytlSetBool(value, key) |
Write BOOL |
ytlSetBool(NO, @"noAds"); |
ytlSetInt(value, key) |
Write NSInteger |
ytlSetInt(2, @"speedIndex"); |
These macros expand to direct YTLUserDefaults method calls, maintaining the singleton pattern while eliminating boilerplate. For example, ytlBool(@"noAds") expands to [[YTLUserDefaults standardUserDefaults] boolForKey:@"noAds"].
Practical Usage Examples
Direct Singleton Access
For code requiring explicit control or testing, the singleton methods are available:
// Reading a preference
BOOL adsDisabled = [[YTLUserDefaults standardUserDefaults] boolForKey:@"noAds"];
// Writing a preference
[[YTLUserDefaults standardUserDefaults] setBool:YES
forKey:@"backgroundPlayback"];
Using Convenience Macros
The typical pattern throughout YTLite.x and other implementation files:
// Feature-gating based on user preference
if (ytlBool(@"noAds")) {
// ... remove advertisement views from hierarchy
}
// Adjusting playback behavior
ytlSetInt(2, @"speedIndex"); // Set to 2× speed
NSInteger currentSpeed = ytlInt(@"speedIndex");
Resetting All Preferences
The Settings UI provides a "Reset All Settings" option that calls:
[YTLUserDefaults resetUserDefaults];
This class method (defined in Utils/YTLUserDefaults.m lines 36-38) immediately clears the entire com.dvntm.ytlite suite, restoring all defaults on next launch.
The Reset Mechanism
Complete preference wiping is handled by two methods in Utils/YTLUserDefaults.m (lines 19-22 and 36-38):
- (void)reset {
[self removePersistentDomainForName:kDefaultsSuiteName];
}
+ (void)resetUserDefaults {
[[self standardUserDefaults] reset];
}
The instance method -reset uses NSUserDefaults' -removePersistentDomainForName: to atomically delete all keys in the suite. The class method provides the convenient entry point used by Settings.x at line 594 when users confirm the reset action.
Key Files in the Preference System
| File | Purpose | Location |
|---|---|---|
Utils/YTLUserDefaults.h |
Class declaration and public API | Utils/YTLUserDefaults.h |
Utils/YTLUserDefaults.m |
Singleton implementation, defaults registration, reset logic | Utils/YTLUserDefaults.m |
YTLite.h |
Macro definitions (ytlBool, ytlSetInt, etc.) |
YTLite.h |
Settings.x |
UI implementation including reset functionality | Settings.x |
YTLite.x |
Primary usage of preference macros for feature gating | YTLite.x |
Summary
- YTLUserDefaults is a specialized
NSUserDefaultssubclass that scopes all YTLite preferences to thecom.dvntm.ytlitesuite - The singleton pattern with
dispatch_onceensures thread-safe, single-instance access across the entire tweak - Baseline defaults are registered automatically on first launch, giving every feature a defined initial state
- Convenience macros (
ytlBool,ytlSetInt, etc.) provide terse, type-safe access throughout the codebase - Complete reset is available through
[YTLUserDefaults resetUserDefaults], which clears the entire suite
Frequently Asked Questions
What is the difference between YTLUserDefaults and standard NSUserDefaults?
YTLUserDefaults is a subclass that creates an isolated suite named com.dvntm.ytlite, keeping YTLite's preferences completely separate from YouTube's own settings or other tweaks. It also adds singleton enforcement, default registration, and reset functionality that standard NSUserDefaults doesn't provide.
How does YTLUserDefaults handle first-time installation?
On first access to [YTLUserDefaults standardUserDefaults], the dispatch_once block calls -registerDefaults, which populates the suite with baseline values for every toggle (e.g., noAds: @YES). This ensures the tweak works immediately after installation without requiring users to configure anything first.
Can I use YTLUserDefaults for my own iOS tweak?
The pattern is highly reusable. The key components are: a suite name constant, a singleton accessor with dispatch_once, default registration, and convenience macros. However, you should change kDefaultsSuiteName to your own reverse-DNS identifier to avoid conflicts with YTLite or other tweaks.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →