How YTLite Modifies the YouTube Tab Bar Navigation: A Complete Technical Breakdown
YTLite modifies the YouTube tab bar navigation by injecting preference-driven hooks into YTPivotBarView, YTPivotBarItemView, and YTPivotBarIndicatorView using MobileSubstrate, allowing users to hide, reorder, and customize tabs at runtime.
YTLite is a popular iOS tweak that enhances the YouTube app with extensive customization options. One of its most powerful features is tab bar navigation modification — the ability to remove unwanted tabs, restore the Explore tab, hide labels and indicators, and even enable a "Shorts-only" mode. This deep dive examines the actual source code from the dayanch96/YTLite repository to explain exactly how these modifications work.
How YTLite Settings Control the Tab Bar
The YTLite tab bar modification system begins in the Settings panel, where users toggle preferences that are stored as boolean values and later read by the runtime hooks.
The Tabbar Settings Section in Settings.x
In Settings.x (lines 76-93), YTLite constructs a dedicated Tabbar section containing multiple toggle switches:
| Setting | Preference Key | Effect |
|---|---|---|
| Remove Labels | removeLabels |
Hides tab title text |
| Remove Indicators | removeIndicators |
Hides notification dots/badges |
| Re-Explore | reExplore |
Restores Explore tab if removed |
| Add Explore | addExplore |
Forces Explore tab to appear |
| Hide Shorts Tab | removeShorts |
Removes Shorts tab |
| Hide Subscriptions Tab | removeSubscriptions |
Removes Subscriptions tab |
| Hide Upload Button | removeUploads |
Removes Upload tab |
| Hide Library Tab | removeLibrary |
Removes Library tab |
Each switch uses helper methods ytlBool and ytlSetBool to read and persist these preferences, which are then accessed by the runtime hooks in YTLite.x.
Core Tab Bar Modification Logic in YTLite.x
The primary tab bar modification occurs in YTLite.x through MobileSubstrate hooks targeting YTPivotBarView. The %hook YTPivotBarView → setRenderer: method (lines 44-78) implements the complete tab filtering and insertion logic.
How YTLite Filters and Removes Tabs
The hook intercepts the pivot bar renderer before it displays and modifies its itemsArray:
%hook YTPivotBarView
- (void)setRenderer:(YTIPivotBarRenderer *)renderer {
NSMutableArray<YTIPivotBarSupportedRenderers *> *items = [renderer itemsArray];
// Map tab identifiers to their removal conditions
NSDictionary *identifiersToRemove = @{
@"FEshorts": @[@(ytlBool(@"removeShorts")), @(ytlBool(@"reExplore"))],
@"FEsubscriptions": @[@(ytlBool(@"removeSubscriptions"))],
@"FEuploads": @[@(ytlBool(@"removeUploads"))],
@"FElibrary": @[@(ytlBool(@"removeLibrary"))]
};
// Iterate and remove matching tabs
for (NSString *identifier in identifiersToRemove) {
BOOL shouldRemove = [identifiersToRemove[identifier] containsObject:@(YES)];
if (shouldRemove) {
NSUInteger idx = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *r, NSUInteger i, BOOL *stop) {
return [[[r pivotBarItemRenderer] pivotIdentifier] isEqualToString:identifier];
}];
if (idx != NSNotFound) [items removeObjectAtIndex:idx];
}
}
// Explore tab insertion logic (shown below)...
%orig;
}
%end
The code uses indexOfObjectPassingTest: to find tabs by their pivotIdentifier (YouTube's internal tab IDs like FEshorts, FEsubscriptions, etc.) and removes them from the mutable array before the original setRenderer: implementation processes the modified list.
How YTLite Adds or Restores the Explore Tab
The same hook optionally inserts the Explore tab when it's missing and either reExplore or addExplore is enabled (lines 69-76):
// Inside setRenderer: hook, after removal logic
NSUInteger exploreIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *r, NSUInteger i, BOOL *stop) {
return [[[r pivotBarItemRenderer] pivotIdentifier] isEqualToString:@"FEexplore"];
}];
if (exploreIndex == NSNotFound && (ytlBool(@"reExplore") || ytlBool(@"addExplore"))) {
YTIPivotBarSupportedRenderers *exploreTab = [%c(YTIPivotBarRenderer)
pivotBarItemWithPivotIdentifier:@"FEexplore"
title:LOC(@"Explore")
iconImageName:@"icons_system_explore_24"];
[items insertObject:exploreTab atIndex:1];
}
This creates a new YTIPivotBarSupportedRenderers item using YouTube's internal factory method and inserts it at index 1 (second position) in the tab bar.
Hiding Tab Labels and Indicators
Beyond removing entire tabs, YTLite can also visually minimize the tab bar by hiding text labels and notification indicators.
Removing Tab Labels in YTPivotBarItemView
In YTLite.x lines 90-97, the %hook YTPivotBarItemView → setRenderer: method clears button titles when removeLabels is enabled:
%hook YTPivotBarItemView
- (void)setRenderer:(YTIPivotBarRenderer *)renderer {
%orig;
if (ytlBool(@"removeLabels")) {
[self.navigationButton setTitle:@"" forState:UIControlStateNormal];
[self.navigationButton setSizeWithPaddingAndInsets:NO];
}
}
%end
The setSizeWithPaddingAndInsets:NO call ensures the button resizes appropriately without text content.
Removing Notification Indicators in YTPivotBarIndicatorView
For indicators (the small dots showing new content), YTLite.x lines 84-86 hooks YTPivotBarIndicatorView:
%hook YTPivotBarIndicatorView
- (void)setFillColor:(id)arg1 { %orig(ytlBool(@"removeIndicators") ? [UIColor clearColor] : arg1); }
- (void)setBorderColor:(id)arg1 { %orig(ytlBool(@"removeIndicators") ? [UIColor clearColor] : arg1); }
%end
This forces both fill and border colors to transparent when indicators should be hidden, making them invisible while preserving the view structure.
Default Tab Selection and Shorts-Only Mode
YTLite provides additional navigation control through default tab selection and a specialized Shorts-only mode.
Setting the Default Tab in YTPivotBarViewController
In YTLite.x lines 118-124, the viewDidAppear: hook reads the pivotIndex preference and selects the corresponding tab:
%hook YTPivotBarViewController
- (void)viewDidAppear:(BOOL)animated {
%orig;
NSInteger pivotIndex = ytlInt(@"pivotIndex");
if (pivotIndex > 0 && [self.viewControllers count] >= pivotIndex) {
[self selectItemWithPivotIdentifier:self.viewControllers[pivotIndex - 1].pivotIdentifier];
}
}
%end
The pivotIndex is 1-based in the UI but converted to 0-based array access, allowing users to set any tab as their default landing page.
Enabling Shorts-Only Mode
For users who want a dedicated Shorts experience, YTLite.x lines 18-24 implement shortsOnlyMode:
%hook YTPivotBarViewController
- (void)viewDidAppear:(BOOL)animated {
%orig;
if (ytlBool(@"shortsOnlyMode")) {
[self selectItemWithPivotIdentifier:@"FEshorts"];
[self.parentViewController hidePivotBar];
}
// ... default tab logic
}
%end
This hook automatically selects the Shorts tab (FEshorts) and hides the entire pivot bar, creating a fullscreen Shorts-only interface.
Preventing Pivot Bar Show in Shorts-Only Mode
To ensure the bar stays hidden, YTLite.x lines 33-38 hooks YTAppViewController:
%hook YTAppViewController
- (void)showPivotBar {
if (ytlBool(@"shortsOnlyMode")) {
%orig(NO);
} else {
%orig;
}
}
%end
This intercepts showPivotBar calls and passes NO when shortsOnlyMode is active, suppressing any automatic bar visibility.
Key Implementation Files
| File | Lines | Purpose |
|---|---|---|
Settings.x |
76-93 | Defines the Tabbar settings UI with toggle switches for all tab bar modifications |
YTLite.x |
44-78 | %hook YTPivotBarView → setRenderer: — core logic for removing and adding tabs |
YTLite.x |
69-76 | Explore tab insertion logic when reExplore or addExplore is enabled |
YTLite.x |
84-86 | %hook YTPivotBarIndicatorView — hides notification indicators |
YTLite.x |
90-97 | %hook YTPivotBarItemView — removes tab labels |
YTLite.x |
18-24 | %hook YTPivotBarViewController → viewDidAppear: — Shorts-only mode and default tab selection |
YTLite.x |
33-38 | %hook YTAppViewController → showPivotBar — prevents bar show in Shorts-only mode |
Summary
YTLite modifies the YouTube tab bar navigation through a sophisticated multi-layered injection system:
- Settings layer —
Settings.xprovides a user-friendly picker interface with 8+ toggle switches that persist preferences usingytlBool/ytlSetBool - Tab filtering layer —
%hook YTPivotBarView→setRenderer:inYTLite.xintercepts the pivot bar renderer, maps YouTube's internal identifiers (FEshorts,FEsubscriptions,FEuploads,FElibrary) to preferences, and removes matching tabs from theitemsArray - Tab insertion layer — The same hook conditionally creates and inserts an
Exploretab (FEexplore) at index 1 whenreExploreoraddExploreis enabled - Visual minimization layer — Separate hooks on
YTPivotBarItemViewandYTPivotBarIndicatorViewhide labels and notification indicators without removing the underlying tab structure - Navigation control layer —
YTPivotBarViewControllerhooks implement default tab selection viapivotIndexand the complete "Shorts-only" mode that auto-selects Shorts and hides the entire bar
Frequently Asked Questions
What is the pivot bar in YouTube's iOS app?
The pivot bar is YouTube's internal name for the bottom navigation tab bar that contains tabs like Home, Shorts, Subscriptions, and Library. YTLite hooks into YTPivotBarView, YTIPivotBarRenderer, and related classes to modify this component at runtime. The bar uses identifiers like FEshorts, FEsubscriptions, FEuploads, FElibrary, and FEexplore to distinguish tabs internally.
Can YTLite completely remove the tab bar instead of just hiding tabs?
Yes, through Shorts-only mode. When shortsOnlyMode is enabled in YTLite.x lines 18-24, the tweak calls [self.parentViewController hidePivotBar] and also hooks YTAppViewController → showPivotBar (lines 33-38) to prevent the bar from reappearing. This creates a fullscreen Shorts experience without the bottom navigation bar entirely.
How does YTLite restore the Explore tab that YouTube removed?
YTLite checks if the FEexplore identifier exists in the current itemsArray within the setRenderer: hook (lines 69-76). If exploreIndex == NSNotFound and either reExplore or addExplore is enabled, it constructs a new YTIPivotBarSupportedRenderers instance using %c(YTIPivotBarRenderer)'s factory method with the title "Explore" and icon icons_system_explore_24, then inserts it at index 1 (second position).
Why does YTLite use separate hooks for labels and indicators instead of one hook?
YTLite uses targeted hooks for visual modifications because labels and indicators are rendered by separate view classes with different responsibilities. YTPivotBarItemView manages the button containing the icon and label, so hooking setRenderer: there (lines 90-97) allows clearing the title string. YTPivotBarIndicatorView is a separate sublayer for notification badges, so hooking setFillColor: and setBorderColor: (lines 84-86) forces transparent colors. This separation follows the actual view hierarchy in YouTube's UIKit implementation.
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 →