Rewrite loading frame management (again)

This commit is contained in:
Cameron Gutman 2018-12-28 16:45:05 -08:00
parent 611358e35c
commit 08e169eb23
3 changed files with 43 additions and 83 deletions

View File

@ -10,5 +10,11 @@
@interface LoadingFrameViewController : UIViewController @interface LoadingFrameViewController : UIViewController
- (void)showLoadingFrame:(void (^)(void))completion;
- (void)dismissLoadingFrame:(void (^)(void))completion;
- (BOOL)isShown;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingSpinner; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingSpinner;
@end @end

View File

@ -8,11 +8,9 @@
#import "LoadingFrameViewController.h" #import "LoadingFrameViewController.h"
@interface LoadingFrameViewController () @implementation LoadingFrameViewController {
BOOL presented;
@end };
@implementation LoadingFrameViewController
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
@ -20,19 +18,38 @@
self.loadingSpinner.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2); self.loadingSpinner.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
} }
- (void)didReceiveMemoryWarning { - (UIViewController*) activeViewController {
[super didReceiveMemoryWarning]; UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
// Dispose of any resources that can be recreated.
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
} }
/* - (void)showLoadingFrame:(void (^)(void))completion {
#pragma mark - Navigation if (!presented) {
presented = YES;
// In a storyboard-based application, you will often want to do a little preparation before navigation [[self activeViewController] presentViewController:self animated:NO completion:completion];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { }
// Get the new view controller using [segue destinationViewController]. else if (completion) {
// Pass the selected object to the new view controller. completion();
}
}
- (void)dismissLoadingFrame:(void (^)(void))completion {
if (presented) {
presented = NO;
[self dismissViewControllerAnimated:NO completion:completion];
}
else if (completion) {
completion();
}
}
- (BOOL)isShown {
return presented;
} }
*/
@end @end

View File

@ -48,7 +48,6 @@
NSArray* _sortedAppList; NSArray* _sortedAppList;
NSCache* _boxArtCache; NSCache* _boxArtCache;
bool _background; bool _background;
dispatch_semaphore_t _loadingFrameSemaphore;
#if TARGET_OS_TV #if TARGET_OS_TV
UITapGestureRecognizer* _menuRecognizer; UITapGestureRecognizer* _menuRecognizer;
#else #else
@ -383,20 +382,6 @@ static NSMutableSet* hostList;
return topController; 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 { - (void)hostLongClicked:(TemporaryHost *)host view:(UIView *)view {
Log(LOG_D, @"Long clicked host: %@", host.name); Log(LOG_D, @"Long clicked host: %@", host.name);
UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
@ -677,66 +662,18 @@ static NSMutableSet* hostList;
} }
- (void) showLoadingFrame:(void (^)(void))completion { - (void) showLoadingFrame:(void (^)(void))completion {
// Wait for all loading frame operations to complete before starting this one [_loadingFrame showLoadingFrame:completion];
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();
}
}];
});
});
} }
- (void) hideLoadingFrame:(void (^)(void))completion { - (void) hideLoadingFrame:(void (^)(void))completion {
// Wait for all loading frame operations to complete before starting this one [self enableNavigation];
dispatch_semaphore_wait(_loadingFrameSemaphore, DISPATCH_TIME_FOREVER); [_loadingFrame dismissLoadingFrame:completion];
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();
}
}];
});
});
} }
- (void)viewDidLoad - (void)viewDidLoad
{ {
[super viewDidLoad]; [super viewDidLoad];
// Ensure only one loading frame operation can take place at a time
_loadingFrameSemaphore = dispatch_semaphore_create(1);
#if !TARGET_OS_TV #if !TARGET_OS_TV
// Set the side bar button action. When it's tapped, it'll show the sidebar. // Set the side bar button action. When it's tapped, it'll show the sidebar.
[_limelightLogoButton addTarget:self.revealViewController action:@selector(revealToggle:) forControlEvents:UIControlEventTouchDown]; [_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 // loading frame which will cause an infinite loop by starting
// another loading frame. To avoid this, just don't refresh // another loading frame. To avoid this, just don't refresh
// if we're coming back from a loading frame view. // 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 - (void)viewDidDisappear:(BOOL)animated