mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-10-29 12:00:47 -04:00
619 lines
20 KiB
Objective-C
619 lines
20 KiB
Objective-C
//
|
|
// FLEXTableViewController.m
|
|
// FLEX
|
|
//
|
|
// Created by Tanner on 7/5/19.
|
|
// Copyright © 2020 FLEX Team. All rights reserved.
|
|
//
|
|
|
|
#import "FLEXTableViewController.h"
|
|
#import "FLEXExplorerViewController.h"
|
|
#import "FLEXBookmarksViewController.h"
|
|
#import "FLEXTabsViewController.h"
|
|
#import "FLEXScopeCarousel.h"
|
|
#import "FLEXTableView.h"
|
|
#import "FLEXUtility.h"
|
|
#import "FLEXResources.h"
|
|
#import "UIBarButtonItem+FLEX.h"
|
|
#import <objc/runtime.h>
|
|
|
|
@interface Block : NSObject
|
|
- (void)invoke;
|
|
@end
|
|
|
|
CGFloat const kFLEXDebounceInstant = 0.f;
|
|
CGFloat const kFLEXDebounceFast = 0.05;
|
|
CGFloat const kFLEXDebounceForAsyncSearch = 0.15;
|
|
CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
|
|
|
@interface FLEXTableViewController ()
|
|
@property (nonatomic) NSTimer *debounceTimer;
|
|
@property (nonatomic) BOOL didInitiallyRevealSearchBar;
|
|
@property (nonatomic) UITableViewStyle style;
|
|
|
|
@property (nonatomic) BOOL hasAppeared;
|
|
@property (nonatomic, readonly) UIView *tableHeaderViewContainer;
|
|
|
|
@property (nonatomic, readonly) BOOL manuallyDeactivateSearchOnDisappear;
|
|
|
|
@property (nonatomic) UIBarButtonItem *middleToolbarItem;
|
|
@property (nonatomic) UIBarButtonItem *middleLeftToolbarItem;
|
|
@property (nonatomic) UIBarButtonItem *leftmostToolbarItem;
|
|
@end
|
|
|
|
@implementation FLEXTableViewController
|
|
@dynamic tableView;
|
|
@synthesize showsShareToolbarItem = _showsShareToolbarItem;
|
|
@synthesize tableHeaderViewContainer = _tableHeaderViewContainer;
|
|
@synthesize automaticallyShowsSearchBarCancelButton = _automaticallyShowsSearchBarCancelButton;
|
|
|
|
#pragma mark - Initialization
|
|
|
|
- (id)init {
|
|
if (@available(iOS 13.0, *)) {
|
|
self = [self initWithStyle:UITableViewStyleInsetGrouped];
|
|
} else {
|
|
self = [self initWithStyle:UITableViewStyleGrouped];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (id)initWithStyle:(UITableViewStyle)style {
|
|
self = [super initWithStyle:style];
|
|
|
|
if (self) {
|
|
_searchBarDebounceInterval = kFLEXDebounceFast;
|
|
_showSearchBarInitially = YES;
|
|
_style = style;
|
|
_manuallyDeactivateSearchOnDisappear = (
|
|
NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11
|
|
);
|
|
|
|
// We will be our own search delegate if we implement this method
|
|
if ([self respondsToSelector:@selector(updateSearchResults:)]) {
|
|
self.searchDelegate = (id)self;
|
|
}
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
#pragma mark - Public
|
|
|
|
- (FLEXWindow *)window {
|
|
return (id)self.view.window;
|
|
}
|
|
|
|
- (void)setShowsSearchBar:(BOOL)showsSearchBar {
|
|
if (_showsSearchBar == showsSearchBar) return;
|
|
_showsSearchBar = showsSearchBar;
|
|
|
|
if (showsSearchBar) {
|
|
UIViewController *results = self.searchResultsController;
|
|
self.searchController = [[UISearchController alloc] initWithSearchResultsController:results];
|
|
self.searchController.searchBar.placeholder = @"Filter";
|
|
self.searchController.searchResultsUpdater = (id)self;
|
|
self.searchController.delegate = (id)self;
|
|
self.searchController.dimsBackgroundDuringPresentation = NO;
|
|
self.searchController.hidesNavigationBarDuringPresentation = NO;
|
|
/// Not necessary in iOS 13; remove this when iOS 13 is the minimum deployment target
|
|
self.searchController.searchBar.delegate = self;
|
|
|
|
self.automaticallyShowsSearchBarCancelButton = YES;
|
|
|
|
if (@available(iOS 13, *)) {
|
|
self.searchController.automaticallyShowsScopeBar = NO;
|
|
}
|
|
|
|
[self addSearchController:self.searchController];
|
|
} else {
|
|
// Search already shown and just set to NO, so remove it
|
|
[self removeSearchController:self.searchController];
|
|
}
|
|
}
|
|
|
|
- (void)setShowsCarousel:(BOOL)showsCarousel {
|
|
if (_showsCarousel == showsCarousel) return;
|
|
_showsCarousel = showsCarousel;
|
|
|
|
if (showsCarousel) {
|
|
_carousel = ({ weakify(self)
|
|
|
|
FLEXScopeCarousel *carousel = [FLEXScopeCarousel new];
|
|
carousel.selectedIndexChangedAction = ^(NSInteger idx) { strongify(self);
|
|
[self.searchDelegate updateSearchResults:self.searchText];
|
|
};
|
|
|
|
// UITableView won't update the header size unless you reset the header view
|
|
[carousel registerBlockForDynamicTypeChanges:^(FLEXScopeCarousel *_) { strongify(self);
|
|
[self layoutTableHeaderIfNeeded];
|
|
}];
|
|
|
|
carousel;
|
|
});
|
|
[self addCarousel:_carousel];
|
|
} else {
|
|
// Carousel already shown and just set to NO, so remove it
|
|
[self removeCarousel:_carousel];
|
|
}
|
|
}
|
|
|
|
- (NSInteger)selectedScope {
|
|
if (self.searchController.searchBar.showsScopeBar) {
|
|
return self.searchController.searchBar.selectedScopeButtonIndex;
|
|
} else if (self.showsCarousel) {
|
|
return self.carousel.selectedIndex;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
- (void)setSelectedScope:(NSInteger)selectedScope {
|
|
if (self.searchController.searchBar.showsScopeBar) {
|
|
self.searchController.searchBar.selectedScopeButtonIndex = selectedScope;
|
|
} else if (self.showsCarousel) {
|
|
self.carousel.selectedIndex = selectedScope;
|
|
}
|
|
|
|
[self.searchDelegate updateSearchResults:self.searchText];
|
|
}
|
|
|
|
- (NSString *)searchText {
|
|
return self.searchController.searchBar.text;
|
|
}
|
|
|
|
- (BOOL)automaticallyShowsSearchBarCancelButton {
|
|
if (@available(iOS 13, *)) {
|
|
return self.searchController.automaticallyShowsCancelButton;
|
|
}
|
|
|
|
return _automaticallyShowsSearchBarCancelButton;
|
|
}
|
|
|
|
- (void)setAutomaticallyShowsSearchBarCancelButton:(BOOL)value {
|
|
if (@available(iOS 13, *)) {
|
|
self.searchController.automaticallyShowsCancelButton = value;
|
|
}
|
|
|
|
_automaticallyShowsSearchBarCancelButton = value;
|
|
}
|
|
|
|
- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock {
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
NSArray *items = backgroundBlock();
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
mainBlock(items);
|
|
});
|
|
});
|
|
}
|
|
|
|
- (void)setsShowsShareToolbarItem:(BOOL)showsShareToolbarItem {
|
|
_showsShareToolbarItem = showsShareToolbarItem;
|
|
if (self.isViewLoaded) {
|
|
[self setupToolbarItems];
|
|
}
|
|
}
|
|
|
|
- (void)disableToolbar {
|
|
self.navigationController.toolbarHidden = YES;
|
|
self.navigationController.hidesBarsOnSwipe = NO;
|
|
self.toolbarItems = nil;
|
|
}
|
|
|
|
|
|
#pragma mark - View Controller Lifecycle
|
|
|
|
- (void)loadView {
|
|
self.view = [FLEXTableView style:self.style];
|
|
self.tableView.dataSource = self;
|
|
self.tableView.delegate = self;
|
|
|
|
_shareToolbarItem = FLEXBarButtonItemSystem(Action, self, @selector(shareButtonPressed:));
|
|
_bookmarksToolbarItem = [UIBarButtonItem
|
|
flex_itemWithImage:FLEXResources.bookmarksIcon target:self action:@selector(showBookmarks)
|
|
];
|
|
_openTabsToolbarItem = [UIBarButtonItem
|
|
flex_itemWithImage:FLEXResources.openTabsIcon target:self action:@selector(showTabSwitcher)
|
|
];
|
|
|
|
self.leftmostToolbarItem = UIBarButtonItem.flex_fixedSpace;
|
|
self.middleLeftToolbarItem = UIBarButtonItem.flex_fixedSpace;
|
|
self.middleToolbarItem = UIBarButtonItem.flex_fixedSpace;
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
|
|
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
|
|
|
|
// Toolbar
|
|
self.navigationController.toolbarHidden = self.toolbarItems.count > 0;
|
|
self.navigationController.hidesBarsOnSwipe = YES;
|
|
|
|
// On iOS 13, the root view controller shows it's search bar no matter what.
|
|
// Turning this off avoids some weird flash the navigation bar does when we
|
|
// toggle navigationItem.hidesSearchBarWhenScrolling on and off. The flash
|
|
// will still happen on subsequent view controllers, but we can at least
|
|
// avoid it for the root view controller
|
|
if (@available(iOS 13, *)) {
|
|
if (self.navigationController.viewControllers.firstObject == self) {
|
|
_showSearchBarInitially = NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)viewWillAppear:(BOOL)animated {
|
|
[super viewWillAppear:animated];
|
|
|
|
if (@available(iOS 11.0, *)) {
|
|
// When going back, make the search bar reappear instead of hiding
|
|
if ((self.pinSearchBar || self.showSearchBarInitially) && !self.didInitiallyRevealSearchBar) {
|
|
self.navigationItem.hidesSearchBarWhenScrolling = NO;
|
|
}
|
|
}
|
|
|
|
// Make the keyboard seem to appear faster
|
|
if (self.activatesSearchBarAutomatically) {
|
|
[self makeKeyboardAppearNow];
|
|
}
|
|
|
|
[self setupToolbarItems];
|
|
}
|
|
|
|
- (void)viewDidAppear:(BOOL)animated {
|
|
[super viewDidAppear:animated];
|
|
|
|
// Allow scrolling to collapse the search bar, only if we don't want it pinned
|
|
if (@available(iOS 11.0, *)) {
|
|
if (self.showSearchBarInitially && !self.pinSearchBar && !self.didInitiallyRevealSearchBar) {
|
|
// All this mumbo jumbo is necessary to work around a bug in iOS 13 up to 13.2
|
|
// wherein quickly toggling navigationItem.hidesSearchBarWhenScrolling to make
|
|
// the search bar appear initially results in a bugged search bar that
|
|
// becomes transparent and floats over the screen as you scroll
|
|
[UIView animateWithDuration:0.2 animations:^{
|
|
self.navigationItem.hidesSearchBarWhenScrolling = YES;
|
|
[self.navigationController.view setNeedsLayout];
|
|
[self.navigationController.view layoutIfNeeded];
|
|
}];
|
|
}
|
|
}
|
|
|
|
if (self.activatesSearchBarAutomatically) {
|
|
// Keyboard has appeared, now we call this as we soon present our search bar
|
|
[self removeDummyTextField];
|
|
|
|
// Activate the search bar
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
// This doesn't work unless it's wrapped in this dispatch_async call
|
|
[self.searchController.searchBar becomeFirstResponder];
|
|
});
|
|
}
|
|
|
|
// We only want to reveal the search bar when the view controller first appears.
|
|
self.didInitiallyRevealSearchBar = YES;
|
|
}
|
|
|
|
- (void)viewWillDisappear:(BOOL)animated {
|
|
[super viewWillDisappear:animated];
|
|
|
|
if (self.manuallyDeactivateSearchOnDisappear && self.searchController.isActive) {
|
|
self.searchController.active = NO;
|
|
}
|
|
}
|
|
|
|
- (void)didMoveToParentViewController:(UIViewController *)parent {
|
|
[super didMoveToParentViewController:parent];
|
|
// Reset this since we are re-appearing under a new
|
|
// parent view controller and need to show it again
|
|
self.didInitiallyRevealSearchBar = NO;
|
|
}
|
|
|
|
|
|
#pragma mark - Toolbar, Public
|
|
|
|
- (void)setupToolbarItems {
|
|
if (!self.isViewLoaded) {
|
|
return;
|
|
}
|
|
|
|
self.toolbarItems = @[
|
|
self.leftmostToolbarItem,
|
|
UIBarButtonItem.flex_flexibleSpace,
|
|
self.middleLeftToolbarItem,
|
|
UIBarButtonItem.flex_flexibleSpace,
|
|
self.middleToolbarItem,
|
|
UIBarButtonItem.flex_flexibleSpace,
|
|
self.bookmarksToolbarItem,
|
|
UIBarButtonItem.flex_flexibleSpace,
|
|
self.openTabsToolbarItem,
|
|
];
|
|
|
|
for (UIBarButtonItem *item in self.toolbarItems) {
|
|
[item _setWidth:60];
|
|
// This does not work for anything but fixed spaces for some reason
|
|
// item.width = 60;
|
|
}
|
|
|
|
// Disable tabs entirely when not presented by FLEXExplorerViewController
|
|
UIViewController *presenter = self.navigationController.presentingViewController;
|
|
if (![presenter isKindOfClass:[FLEXExplorerViewController class]]) {
|
|
self.openTabsToolbarItem.enabled = NO;
|
|
}
|
|
}
|
|
|
|
- (void)addToolbarItems:(NSArray<UIBarButtonItem *> *)items {
|
|
if (self.showsShareToolbarItem) {
|
|
// Share button is in the middle, skip middle button
|
|
if (items.count > 0) {
|
|
self.middleLeftToolbarItem = items[0];
|
|
}
|
|
if (items.count > 1) {
|
|
self.leftmostToolbarItem = items[1];
|
|
}
|
|
} else {
|
|
// Add buttons right-to-left
|
|
if (items.count > 0) {
|
|
self.middleToolbarItem = items[0];
|
|
}
|
|
if (items.count > 1) {
|
|
self.middleLeftToolbarItem = items[1];
|
|
}
|
|
if (items.count > 2) {
|
|
self.leftmostToolbarItem = items[2];
|
|
}
|
|
}
|
|
|
|
[self setupToolbarItems];
|
|
}
|
|
|
|
- (void)setShowsShareToolbarItem:(BOOL)showShare {
|
|
if (_showsShareToolbarItem != showShare) {
|
|
_showsShareToolbarItem = showShare;
|
|
|
|
if (showShare) {
|
|
// Push out leftmost item
|
|
self.leftmostToolbarItem = self.middleLeftToolbarItem;
|
|
self.middleLeftToolbarItem = self.middleToolbarItem;
|
|
|
|
// Use share for middle
|
|
self.middleToolbarItem = self.shareToolbarItem;
|
|
} else {
|
|
// Remove share, shift custom items rightward
|
|
self.middleToolbarItem = self.middleLeftToolbarItem;
|
|
self.middleLeftToolbarItem = self.leftmostToolbarItem;
|
|
self.leftmostToolbarItem = UIBarButtonItem.flex_fixedSpace;
|
|
}
|
|
}
|
|
|
|
[self setupToolbarItems];
|
|
}
|
|
|
|
- (void)shareButtonPressed:(UIBarButtonItem *)sender {
|
|
|
|
}
|
|
|
|
|
|
#pragma mark - Private
|
|
|
|
- (void)debounce:(void(^)(void))block {
|
|
[self.debounceTimer invalidate];
|
|
|
|
self.debounceTimer = [NSTimer
|
|
scheduledTimerWithTimeInterval:self.searchBarDebounceInterval
|
|
target:block
|
|
selector:@selector(invoke)
|
|
userInfo:nil
|
|
repeats:NO
|
|
];
|
|
}
|
|
|
|
- (void)layoutTableHeaderIfNeeded {
|
|
if (self.showsCarousel) {
|
|
self.carousel.frame = FLEXRectSetHeight(
|
|
self.carousel.frame, self.carousel.intrinsicContentSize.height
|
|
);
|
|
}
|
|
|
|
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
|
|
}
|
|
|
|
- (void)addCarousel:(FLEXScopeCarousel *)carousel {
|
|
if (@available(iOS 11.0, *)) {
|
|
self.tableView.tableHeaderView = carousel;
|
|
} else {
|
|
carousel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
|
|
|
|
CGRect frame = self.tableHeaderViewContainer.frame;
|
|
CGRect subviewFrame = carousel.frame;
|
|
subviewFrame.origin.y = 0;
|
|
|
|
// Put the carousel below the search bar if it's already there
|
|
if (self.showsSearchBar) {
|
|
carousel.frame = subviewFrame = FLEXRectSetY(
|
|
subviewFrame, self.searchController.searchBar.frame.size.height
|
|
);
|
|
frame.size.height += carousel.intrinsicContentSize.height;
|
|
} else {
|
|
frame.size.height = carousel.intrinsicContentSize.height;
|
|
}
|
|
|
|
self.tableHeaderViewContainer.frame = frame;
|
|
[self.tableHeaderViewContainer addSubview:carousel];
|
|
}
|
|
|
|
[self layoutTableHeaderIfNeeded];
|
|
}
|
|
|
|
- (void)removeCarousel:(FLEXScopeCarousel *)carousel {
|
|
[carousel removeFromSuperview];
|
|
|
|
if (@available(iOS 11.0, *)) {
|
|
self.tableView.tableHeaderView = nil;
|
|
} else {
|
|
if (self.showsSearchBar) {
|
|
[self removeSearchController:self.searchController];
|
|
[self addSearchController:self.searchController];
|
|
} else {
|
|
self.tableView.tableHeaderView = nil;
|
|
_tableHeaderViewContainer = nil;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)addSearchController:(UISearchController *)controller {
|
|
if (@available(iOS 11.0, *)) {
|
|
self.navigationItem.searchController = controller;
|
|
} else {
|
|
controller.searchBar.autoresizingMask |= UIViewAutoresizingFlexibleBottomMargin;
|
|
[self.tableHeaderViewContainer addSubview:controller.searchBar];
|
|
CGRect subviewFrame = controller.searchBar.frame;
|
|
CGRect frame = self.tableHeaderViewContainer.frame;
|
|
frame.size.width = MAX(frame.size.width, subviewFrame.size.width);
|
|
frame.size.height = subviewFrame.size.height;
|
|
|
|
// Move the carousel down if it's already there
|
|
if (self.showsCarousel) {
|
|
self.carousel.frame = FLEXRectSetY(
|
|
self.carousel.frame, subviewFrame.size.height
|
|
);
|
|
frame.size.height += self.carousel.frame.size.height;
|
|
}
|
|
|
|
self.tableHeaderViewContainer.frame = frame;
|
|
[self layoutTableHeaderIfNeeded];
|
|
}
|
|
}
|
|
|
|
- (void)removeSearchController:(UISearchController *)controller {
|
|
if (@available(iOS 11.0, *)) {
|
|
self.navigationItem.searchController = nil;
|
|
} else {
|
|
[controller.searchBar removeFromSuperview];
|
|
|
|
if (self.showsCarousel) {
|
|
// self.carousel.frame = FLEXRectRemake(CGPointZero, self.carousel.frame.size);
|
|
[self removeCarousel:self.carousel];
|
|
[self addCarousel:self.carousel];
|
|
} else {
|
|
self.tableView.tableHeaderView = nil;
|
|
_tableHeaderViewContainer = nil;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (UIView *)tableHeaderViewContainer {
|
|
if (!_tableHeaderViewContainer) {
|
|
_tableHeaderViewContainer = [UIView new];
|
|
self.tableView.tableHeaderView = self.tableHeaderViewContainer;
|
|
}
|
|
|
|
return _tableHeaderViewContainer;
|
|
}
|
|
|
|
- (void)showBookmarks {
|
|
UINavigationController *nav = [[UINavigationController alloc]
|
|
initWithRootViewController:[FLEXBookmarksViewController new]
|
|
];
|
|
[self presentViewController:nav animated:YES completion:nil];
|
|
}
|
|
|
|
- (void)showTabSwitcher {
|
|
UINavigationController *nav = [[UINavigationController alloc]
|
|
initWithRootViewController:[FLEXTabsViewController new]
|
|
];
|
|
[self presentViewController:nav animated:YES completion:nil];
|
|
}
|
|
|
|
|
|
#pragma mark - Search Bar
|
|
|
|
#pragma mark Faster keyboard
|
|
|
|
static UITextField *kDummyTextField = nil;
|
|
|
|
/// Make the keyboard appear instantly. We use this to make the
|
|
/// keyboard appear faster when the search bar is set to appear initially.
|
|
/// You must call \c -removeDummyTextField before your search bar is to appear.
|
|
- (void)makeKeyboardAppearNow {
|
|
if (!kDummyTextField) {
|
|
kDummyTextField = [UITextField new];
|
|
kDummyTextField.autocorrectionType = UITextAutocorrectionTypeNo;
|
|
}
|
|
|
|
kDummyTextField.inputAccessoryView = self.searchController.searchBar.inputAccessoryView;
|
|
[UIApplication.sharedApplication.keyWindow addSubview:kDummyTextField];
|
|
[kDummyTextField becomeFirstResponder];
|
|
}
|
|
|
|
- (void)removeDummyTextField {
|
|
if (kDummyTextField.superview) {
|
|
[kDummyTextField removeFromSuperview];
|
|
}
|
|
}
|
|
|
|
#pragma mark UISearchResultsUpdating
|
|
|
|
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
|
|
[self.debounceTimer invalidate];
|
|
NSString *text = searchController.searchBar.text;
|
|
|
|
void (^updateSearchResults)(void) = ^{
|
|
if (self.searchResultsUpdater) {
|
|
[self.searchResultsUpdater updateSearchResults:text];
|
|
} else {
|
|
[self.searchDelegate updateSearchResults:text];
|
|
}
|
|
};
|
|
|
|
// Only debounce if we want to, and if we have a non-empty string
|
|
// Empty string events are sent instantly
|
|
if (text.length && self.searchBarDebounceInterval > kFLEXDebounceInstant) {
|
|
[self debounce:updateSearchResults];
|
|
} else {
|
|
updateSearchResults();
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark UISearchControllerDelegate
|
|
|
|
- (void)willPresentSearchController:(UISearchController *)searchController {
|
|
// Manually show cancel button for < iOS 13
|
|
if (!@available(iOS 13, *) && self.automaticallyShowsSearchBarCancelButton) {
|
|
[searchController.searchBar setShowsCancelButton:YES animated:YES];
|
|
}
|
|
}
|
|
|
|
- (void)willDismissSearchController:(UISearchController *)searchController {
|
|
// Manually hide cancel button for < iOS 13
|
|
if (!@available(iOS 13, *) && self.automaticallyShowsSearchBarCancelButton) {
|
|
[searchController.searchBar setShowsCancelButton:NO animated:YES];
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark UISearchBarDelegate
|
|
|
|
/// Not necessary in iOS 13; remove this when iOS 13 is the deployment target
|
|
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
|
|
[self updateSearchResultsForSearchController:self.searchController];
|
|
}
|
|
|
|
|
|
#pragma mark Table View
|
|
|
|
/// Not having a title in the first section looks weird with a rounded-corner table view style
|
|
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
|
if (@available(iOS 13, *)) {
|
|
if (self.style == UITableViewStyleInsetGrouped) {
|
|
return @" ";
|
|
}
|
|
}
|
|
|
|
return nil; // For plain/gropued style
|
|
}
|
|
|
|
@end
|