From 08e169eb232733c711a4359561f19fe427561aba Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 28 Dec 2018 16:45:05 -0800 Subject: [PATCH] Rewrite loading frame management (again) --- .../LoadingFrameViewController.h | 6 ++ .../LoadingFrameViewController.m | 49 ++++++++----- .../ViewControllers/MainFrameViewController.m | 71 ++----------------- 3 files changed, 43 insertions(+), 83 deletions(-) diff --git a/Limelight/ViewControllers/LoadingFrameViewController.h b/Limelight/ViewControllers/LoadingFrameViewController.h index 0635725..eb48071 100644 --- a/Limelight/ViewControllers/LoadingFrameViewController.h +++ b/Limelight/ViewControllers/LoadingFrameViewController.h @@ -10,5 +10,11 @@ @interface LoadingFrameViewController : UIViewController +- (void)showLoadingFrame:(void (^)(void))completion; + +- (void)dismissLoadingFrame:(void (^)(void))completion; + +- (BOOL)isShown; + @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingSpinner; @end diff --git a/Limelight/ViewControllers/LoadingFrameViewController.m b/Limelight/ViewControllers/LoadingFrameViewController.m index 340464e..8f95b18 100644 --- a/Limelight/ViewControllers/LoadingFrameViewController.m +++ b/Limelight/ViewControllers/LoadingFrameViewController.m @@ -8,11 +8,9 @@ #import "LoadingFrameViewController.h" -@interface LoadingFrameViewController () - -@end - -@implementation LoadingFrameViewController +@implementation LoadingFrameViewController { + BOOL presented; +}; - (void)viewDidLoad { [super viewDidLoad]; @@ -20,19 +18,38 @@ self.loadingSpinner.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2); } -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. +- (UIViewController*) activeViewController { + UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; + + while (topController.presentedViewController) { + topController = topController.presentedViewController; + } + + return topController; } -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. +- (void)showLoadingFrame:(void (^)(void))completion { + if (!presented) { + presented = YES; + [[self activeViewController] presentViewController:self animated:NO completion:completion]; + } + else if (completion) { + completion(); + } +} + +- (void)dismissLoadingFrame:(void (^)(void))completion { + if (presented) { + presented = NO; + [self dismissViewControllerAnimated:NO completion:completion]; + } + else if (completion) { + completion(); + } +} + +- (BOOL)isShown { + return presented; } -*/ @end diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 75d6eab..3f8a965 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -48,7 +48,6 @@ NSArray* _sortedAppList; NSCache* _boxArtCache; bool _background; - dispatch_semaphore_t _loadingFrameSemaphore; #if TARGET_OS_TV UITapGestureRecognizer* _menuRecognizer; #else @@ -383,20 +382,6 @@ static NSMutableSet* hostList; return topController; } -- (BOOL) loadingFrameIsPresented { - UIViewController *nextController = [UIApplication sharedApplication].keyWindow.rootViewController; - - while (nextController) { - if (nextController == _loadingFrame) { - return YES; - } - - nextController = nextController.presentedViewController; - } - - return NO; -} - - (void)hostLongClicked:(TemporaryHost *)host view:(UIView *)view { Log(LOG_D, @"Long clicked host: %@", host.name); UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet]; @@ -677,66 +662,18 @@ static NSMutableSet* hostList; } - (void) showLoadingFrame:(void (^)(void))completion { - // Wait for all loading frame operations to complete before starting this one - dispatch_semaphore_wait(_loadingFrameSemaphore, DISPATCH_TIME_FOREVER); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - dispatch_async(dispatch_get_main_queue(), ^{ - // If loading frame is already active, just complete it now otherwise - // we may not get a completion callback. - if ([self loadingFrameIsPresented]) { - dispatch_semaphore_signal(self->_loadingFrameSemaphore); - if (completion) { - completion(); - } - return; - } - - // Avoid animating this as it significantly prolongs the loading frame's time on screen - [[self activeViewController] presentViewController:self->_loadingFrame animated:NO completion:^{ - dispatch_semaphore_signal(self->_loadingFrameSemaphore); - if (completion) { - completion(); - } - }]; - }); - }); + [_loadingFrame showLoadingFrame:completion]; } - (void) hideLoadingFrame:(void (^)(void))completion { - // Wait for all loading frame operations to complete before starting this one - dispatch_semaphore_wait(_loadingFrameSemaphore, DISPATCH_TIME_FOREVER); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - dispatch_async(dispatch_get_main_queue(), ^{ - // If loading frame is already dismissed, just complete it now otherwise - // we may not get a completion callback. - if (![self loadingFrameIsPresented]) { - [self enableNavigation]; - dispatch_semaphore_signal(self->_loadingFrameSemaphore); - if (completion) { - completion(); - } - return; - } - - // See comment above in showLoadingFrame about why we don't animate this - [self->_loadingFrame dismissViewControllerAnimated:NO completion:^{ - [self enableNavigation]; - dispatch_semaphore_signal(self->_loadingFrameSemaphore); - if (completion) { - completion(); - } - }]; - }); - }); + [self enableNavigation]; + [_loadingFrame dismissLoadingFrame:completion]; } - (void)viewDidLoad { [super viewDidLoad]; - // Ensure only one loading frame operation can take place at a time - _loadingFrameSemaphore = dispatch_semaphore_create(1); - #if !TARGET_OS_TV // Set the side bar button action. When it's tapped, it'll show the sidebar. [_limelightLogoButton addTarget:self.revealViewController action:@selector(revealToggle:) forControlEvents:UIControlEventTouchDown]; @@ -888,7 +825,7 @@ static NSMutableSet* hostList; // loading frame which will cause an infinite loop by starting // another loading frame. To avoid this, just don't refresh // if we're coming back from a loading frame view. - [self beginForegroundRefresh: ![[self activeViewController] isKindOfClass:[LoadingFrameViewController class]]]; + [self beginForegroundRefresh: !([_loadingFrame isShown] || [_loadingFrame isBeingDismissed])]; } - (void)viewDidDisappear:(BOOL)animated