# How YTLite Manages Preferences and Data Using YTLUserDefaults

> Discover how YTLite manages user preferences and data efficiently using its YTLUserDefaults class. Learn about its singleton pattern and macaque-wrapped functionalities for seamless data handling.

- Repository: [Dan/YTLite](https://github.com/dayanch96/YTLite)
- Tags: internals
- Published: 2026-04-22

---

**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`](https://github.com/dayanch96/YTLite/blob/main/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:

```objc
+ (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_once` guarantees exactly one initialization regardless of thread contention
- `initWithSuiteName:` creates an isolated preferences container that persists across app launches
- `registerDefaults` immediately 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:

```objc
- (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`](https://github.com/dayanch96/YTLite/blob/main/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:

```objc
// 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:

```objc
// 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:

```objc
[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):

```objc
- (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`](https://github.com/dayanch96/YTLite/blob/main/Utils/YTLUserDefaults.h) | Class declaration and public API | [Utils/YTLUserDefaults.h](https://github.com/dayanch96/YTLite/blob/main/Utils/YTLUserDefaults.h) |
| `Utils/YTLUserDefaults.m` | Singleton implementation, defaults registration, reset logic | [Utils/YTLUserDefaults.m](https://github.com/dayanch96/YTLite/blob/main/Utils/YTLUserDefaults.m) |
| [`YTLite.h`](https://github.com/dayanch96/YTLite/blob/main/YTLite.h) | Macro definitions (`ytlBool`, `ytlSetInt`, etc.) | [YTLite.h](https://github.com/dayanch96/YTLite/blob/main/YTLite.h) |
| `Settings.x` | UI implementation including reset functionality | [Settings.x](https://github.com/dayanch96/YTLite/blob/main/Settings.x) |
| `YTLite.x` | Primary usage of preference macros for feature gating | [YTLite.x](https://github.com/dayanch96/YTLite/blob/main/YTLite.x) |

## Summary

- **YTLUserDefaults** is a specialized `NSUserDefaults` subclass that scopes all YTLite preferences to the `com.dvntm.ytlite` suite
- The **singleton pattern** with `dispatch_once` ensures 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.