diff --git a/.gitignore b/.gitignore index 7aee0c65a..c0acb979b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ build/ *.perspectivev3 xcuserdata/ *.xccheckout +*.xcscmblueprint # old skool .svn diff --git a/.travis.yml b/.travis.yml index 3a4a9281b..367c4f282 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: objective-c -xcode_workspace: MBProgressHUD.xcworkspace -xcode_scheme: HudDemo -xcode_sdk: iphonesimulator +osx_image: xcode7.2 +script: + - xctool -workspace MBProgressHUD.xcworkspace -scheme HudTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPad Air 2,OS=9.2" build test GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/CHANGELOG.mdown b/CHANGELOG.mdown new file mode 100644 index 000000000..d50226395 --- /dev/null +++ b/CHANGELOG.mdown @@ -0,0 +1,94 @@ +**Version 0.9.2** @ 22.12.15 + + - Timer improvements + - Additional assertions + - Added a framework target + - Tint progress tint color enhancements + +**Version 0.9.1** @ 06.03.15 + + - Bug-fixes + - Modernization + +**Version 0.9** @ 12.08.14 + + - iOS 8 compatibility and some bug fixes. + - Additional iOS 7 / iOS 8 styling enhancements. + - Improved 64bit support. + - Demo modernization. + +**Version 0.8** @ 19.09.13 + +- iOS 7 compatibility and some bug fixes. + +**Version 0.7** @ 25.06.13 + +- Added horizontal bar mode. ([jjxtra](https://github.com/jjxtra)). +- CI integration. + +**Version 0.6** @ 13.03.13 + +- Full cocoapods support. +- Static library integration option. +- Improved blocks support. +- Bezel color. +- Demo app fixes (iOS 6). +- Various bug-fixes and enhancements. + +**Version 0.5** @ 22.03.12 + +- Major source code modernization and cleanup (KVO, layout code, instance vars, etc.). +- New annular determinate mode. +- New text only mode. +- Added a static library project and Xcode 4 workspace. +- Added methods to find and return HUD(s) on a view. +- Various bug fixes. +- Various demo project enhancements (hi-res rescues, new samples). + +IMPORTANT: Requires LLVM 3+. + +**Version 0.41** @ 03.01.12 + +- Support for ARC. + +**Version 0.4** @ 25.07.10 + +- Different animation modes. Default set to zoom. +- Class convenience methods ([tadelv](http://github.com/tadelv)). +- Autorotation when added to a UIWindow ([wuf810](http://github.com/wuf810)). +- Extended demo app. +- Several smaller fixes. + +**Version 0.33** @ 27.03.10 + +- Custom view operation mode added. +- Fixed a memory leak. + +**Version 0.32** @ 4.01.10 + +- Added minShowTime, graceTime, xOffset, yOffset. +- Various fixes. + +**Version 0.31** @ 8.10.09 + +- Fix for touch through during the fade-out animation. + +**Version 0.3** @ 30.9.09 + +- Added show: and hide: methods. +- Now using UIViews layoutSubviews to automate layout calls. +- Added some floors to round pixel positions and thereby prevent unsharp views. +- Some additional documentation and code cleanup. + +**Version 0.2** @ 21.7.09 + +- Added determinate progress mode and switching capabilities between determinate and indeterminate modes. +- Various bug-fixes. + +**Version 0.11** @ 2.6.09. + +- Updated labelText and detailsLabelText properties to support text modifications while the HUD is being shown. + +**Version 0.1** @ 2.4.09 + +- Initial release. \ No newline at end of file diff --git a/Demo/Classes/HudDemoAppDelegate.h b/Demo/Classes/HudDemoAppDelegate.h deleted file mode 100644 index 1b144a05a..000000000 --- a/Demo/Classes/HudDemoAppDelegate.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// HudDemoAppDelegate.h -// HudDemo -// -// Created by Matej Bukovinski on 2.4.09. -// Copyright bukovinski.com 2009. All rights reserved. -// - -#import - -@class HudDemoViewController; - - -@interface HudDemoAppDelegate : NSObject { - UIWindow *window; - UINavigationController *navController; -} - -@property (nonatomic, retain) IBOutlet UIWindow *window; -@property (nonatomic, retain) IBOutlet UINavigationController *navController; - -@end - diff --git a/Demo/Classes/HudDemoAppDelegate.m b/Demo/Classes/HudDemoAppDelegate.m deleted file mode 100644 index e4488fe77..000000000 --- a/Demo/Classes/HudDemoAppDelegate.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// HudDemoAppDelegate.m -// HudDemo -// -// Created by Matej Bukovinski on 2.4.09. -// Copyright bukovinski.com 2009. All rights reserved. -// - -#import "HudDemoAppDelegate.h" -#import "HudDemoViewController.h" - - -@implementation HudDemoAppDelegate - -@synthesize window; -@synthesize navController; - -- (void)applicationDidFinishLaunching:(UIApplication *)application { - window.rootViewController = navController; - [window makeKeyAndVisible]; -} - -- (void)dealloc { - [navController release]; - [window release]; - [super dealloc]; -} - -@end diff --git a/Demo/Classes/HudDemoViewController.m b/Demo/Classes/HudDemoViewController.m deleted file mode 100644 index 79bbb75ef..000000000 --- a/Demo/Classes/HudDemoViewController.m +++ /dev/null @@ -1,334 +0,0 @@ -// -// HudDemoViewController.m -// HudDemo -// -// Created by Matej Bukovinski on 30.9.09. -// Copyright bukovinski.com 2009. All rights reserved. -// - -#import "HudDemoViewController.h" -#import "MBProgressHUD.h" -#import - - -#define SCREENSHOT_MODE 0 - -#ifndef kCFCoreFoundationVersionNumber_iOS_8_0 - #define kCFCoreFoundationVersionNumber_iOS_7_0 847.20 -#endif - - -@interface HudDemoViewController () { - MBProgressHUD *HUD; - long long expectedLength; - long long currentLength; -} - -@property (retain, nonatomic) IBOutletCollection(UIButton) NSArray *buttons; - -@end - - -@implementation HudDemoViewController - -#pragma mark - Lifecycle methods - -- (void)viewDidLoad { - UIView *content = [[self.view subviews] objectAtIndex:0]; -#if SCREENSHOT_MODE - [content.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; -#endif - if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) { - [self.buttons setValue:@5.f forKeyPath:@"layer.cornerRadius"]; - } else { - [self.buttons setValue:nil forKey:@"backgroundColor"]; - } - ((UIScrollView *)self.view).contentSize = content.bounds.size; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - return YES; -} - -- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { - UIView *content = [[self.view subviews] objectAtIndex:0]; - ((UIScrollView *)self.view).contentSize = content.bounds.size; -} - -- (void)dealloc { - [_buttons release]; - [super dealloc]; -} - -#pragma mark - Actions - -- (IBAction)showSimple:(id)sender { - // The hud will dispable all input on the view (use the higest view possible in the view hierarchy) - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - // Regiser for HUD callbacks so we can remove it from the window at the right time - HUD.delegate = self; - - // Show the HUD while the provided method executes in a new thread - [HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showWithLabel:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - HUD.delegate = self; - HUD.labelText = @"Loading"; - - [HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showWithDetailsLabel:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - HUD.delegate = self; - HUD.labelText = @"Loading"; - HUD.detailsLabelText = @"updating data"; - HUD.square = YES; - - [HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showWithLabelDeterminate:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - // Set determinate mode - HUD.mode = MBProgressHUDModeDeterminate; - - HUD.delegate = self; - HUD.labelText = @"Loading"; - - // myProgressTask uses the HUD instance to update progress - [HUD showWhileExecuting:@selector(myProgressTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showWIthLabelAnnularDeterminate:(id)sender { - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - // Set determinate mode - HUD.mode = MBProgressHUDModeAnnularDeterminate; - - HUD.delegate = self; - HUD.labelText = @"Loading"; - - // myProgressTask uses the HUD instance to update progress - [HUD showWhileExecuting:@selector(myProgressTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showWithLabelDeterminateHorizontalBar:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - // Set determinate bar mode - HUD.mode = MBProgressHUDModeDeterminateHorizontalBar; - - HUD.delegate = self; - - // myProgressTask uses the HUD instance to update progress - [HUD showWhileExecuting:@selector(myProgressTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showWithCustomView:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - // The sample image is based on the work by http://www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/ - // Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators) - HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]] autorelease]; - - // Set custom view mode - HUD.mode = MBProgressHUDModeCustomView; - - HUD.delegate = self; - HUD.labelText = @"Completed"; - - [HUD show:YES]; - [HUD hide:YES afterDelay:3]; -} - -- (IBAction)showWithLabelMixed:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - HUD.delegate = self; - HUD.labelText = @"Connecting"; - HUD.minSize = CGSizeMake(135.f, 135.f); - - [HUD showWhileExecuting:@selector(myMixedTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showUsingBlocks:(id)sender { -#if NS_BLOCKS_AVAILABLE - MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:hud]; - hud.labelText = @"With a block"; - - [hud showAnimated:YES whileExecutingBlock:^{ - [self myTask]; - } completionBlock:^{ - [hud removeFromSuperview]; - [hud release]; - }]; -#endif -} - -- (IBAction)showOnWindow:(id)sender { - // The hud will dispable all input on the window - HUD = [[MBProgressHUD alloc] initWithView:self.view.window]; - [self.view.window addSubview:HUD]; - - HUD.delegate = self; - HUD.labelText = @"Loading"; - - [HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showURL:(id)sender { - NSURL *URL = [NSURL URLWithString:@"http://a1408.g.akamai.net/5/1408/1388/2005110403/1a1a1ad948be278cff2d96046ad90768d848b41947aa1986/sample_iPod.m4v.zip"]; - NSURLRequest *request = [NSURLRequest requestWithURL:URL]; - - NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; - [connection start]; - [connection release]; - - HUD = [[MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES] retain]; - HUD.delegate = self; -} - - -- (IBAction)showWithGradient:(id)sender { - - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - HUD.dimBackground = YES; - - // Regiser for HUD callbacks so we can remove it from the window at the right time - HUD.delegate = self; - - // Show the HUD while the provided method executes in a new thread - [HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES]; -} - -- (IBAction)showTextOnly:(id)sender { - - MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; - - // Configure for text only and offset down - hud.mode = MBProgressHUDModeText; - hud.labelText = @"Some message..."; - hud.margin = 10.f; - hud.removeFromSuperViewOnHide = YES; - - [hud hide:YES afterDelay:3]; -} - -- (IBAction)showWithColor:(id)sender{ - HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; - [self.navigationController.view addSubview:HUD]; - - // Set the hud to display with a color - HUD.color = [UIColor colorWithRed:0.23 green:0.50 blue:0.82 alpha:0.90]; - - HUD.delegate = self; - [HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES]; -} - -#pragma mark - Execution code - -- (void)myTask { - // Do something usefull in here instead of sleeping ... - sleep(3); -} - -- (void)myProgressTask { - // This just increases the progress indicator in a loop - float progress = 0.0f; - while (progress < 1.0f) { - progress += 0.01f; - HUD.progress = progress; - usleep(50000); - } -} - -- (void)myMixedTask { - // Indeterminate mode - sleep(2); - // Switch to determinate mode - HUD.mode = MBProgressHUDModeDeterminate; - HUD.labelText = @"Progress"; - float progress = 0.0f; - while (progress < 1.0f) - { - progress += 0.01f; - HUD.progress = progress; - usleep(50000); - } - // Back to indeterminate mode - HUD.mode = MBProgressHUDModeIndeterminate; - HUD.labelText = @"Cleaning up"; - sleep(2); - // UIImageView is a UIKit class, we have to initialize it on the main thread - __block UIImageView *imageView; - dispatch_sync(dispatch_get_main_queue(), ^{ - UIImage *image = [UIImage imageNamed:@"37x-Checkmark.png"]; - imageView = [[UIImageView alloc] initWithImage:image]; - }); - HUD.customView = [imageView autorelease]; - HUD.mode = MBProgressHUDModeCustomView; - HUD.labelText = @"Completed"; - sleep(2); -} - -#pragma mark - NSURLConnectionDelegete - -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { - expectedLength = MAX([response expectedContentLength], 1); - currentLength = 0; - HUD.mode = MBProgressHUDModeDeterminate; -} - -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - currentLength += [data length]; - HUD.progress = currentLength / (CGFloat)expectedLength; -} - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]] autorelease]; - HUD.mode = MBProgressHUDModeCustomView; - [HUD hide:YES afterDelay:2]; -} - -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { - [HUD hide:YES]; -} - -#pragma mark - MBProgressHUDDelegate - -- (void)hudWasHidden:(MBProgressHUD *)hud { - // Remove HUD from screen when the HUD was hidded - [HUD removeFromSuperview]; - [HUD release]; - HUD = nil; -} - -- (void)viewDidUnload { - [self setButtons:nil]; - [super viewDidUnload]; -} -@end diff --git a/Demo/Classes/MBHudDemoAppDelegate.h b/Demo/Classes/MBHudDemoAppDelegate.h new file mode 100644 index 000000000..dc9588e59 --- /dev/null +++ b/Demo/Classes/MBHudDemoAppDelegate.h @@ -0,0 +1,15 @@ +// +// MBHudDemoAppDelegate.h +// HudDemo +// +// Created by Matej Bukovinski on 2.4.09. +// Copyright bukovinski.com 2009-2015. All rights reserved. +// + +#import + +@interface MBHudDemoAppDelegate : NSObject + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/Demo/Classes/MBHudDemoAppDelegate.m b/Demo/Classes/MBHudDemoAppDelegate.m new file mode 100644 index 000000000..4b4b64b5d --- /dev/null +++ b/Demo/Classes/MBHudDemoAppDelegate.m @@ -0,0 +1,20 @@ +// +// MBHudDemoAppDelegate.m +// HudDemo +// +// Created by Matej Bukovinski on 2.4.09. +// Copyright bukovinski.com 2009-2015. All rights reserved. +// + +#import "MBHudDemoAppDelegate.h" +#import "MBHudDemoViewController.h" + + +@implementation MBHudDemoAppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + self.window.tintColor = [UIColor colorWithRed:.337f green:.57f blue:.731f alpha:1.f]; + return YES; +} + +@end diff --git a/Demo/Classes/HudDemoViewController.h b/Demo/Classes/MBHudDemoViewController.h similarity index 51% rename from Demo/Classes/HudDemoViewController.h rename to Demo/Classes/MBHudDemoViewController.h index 6b4013430..231a84c68 100644 --- a/Demo/Classes/HudDemoViewController.h +++ b/Demo/Classes/MBHudDemoViewController.h @@ -3,12 +3,12 @@ // HudDemo // // Created by Matej Bukovinski on 30.9.09. -// Copyright bukovinski.com 2009. All rights reserved. +// Copyright bukovinski.com 2009-2015. All rights reserved. // #import -@interface HudDemoViewController : UIViewController +@interface MBHudDemoViewController : UITableViewController @end diff --git a/Demo/Classes/MBHudDemoViewController.m b/Demo/Classes/MBHudDemoViewController.m new file mode 100644 index 000000000..606340fc2 --- /dev/null +++ b/Demo/Classes/MBHudDemoViewController.m @@ -0,0 +1,385 @@ +// +// MBHudDemoViewController.m +// HudDemo +// +// Created by Matej Bukovinski on 30.9.09. +// Copyright bukovinski.com 2009-2015. All rights reserved. +// + +#import "MBHudDemoViewController.h" +#import "MBProgressHUD.h" + + +@interface MBExample : NSObject + +@property (nonatomic, copy) NSString *title; +@property (nonatomic, assign) SEL selector; + +@end + + +@implementation MBExample + ++ (instancetype)exampleWithTitle:(NSString *)title selector:(SEL)selector { + MBExample *example = [[self class] new]; + example.title = title; + example.selector = selector; + return example; +} + +@end + + +@interface MBHudDemoViewController () + +@property (nonatomic, strong) NSArray *> *examples; +@property (nonatomic, assign) BOOL canceled; + +@end + + +@implementation MBHudDemoViewController + +#pragma mark - Lifecycle + +- (void)awakeFromNib { + [super awakeFromNib]; + self.examples = + @[@[[MBExample exampleWithTitle:@"Indeterminate mode" selector:@selector(indeterminateExample)], + [MBExample exampleWithTitle:@"With label" selector:@selector(labelExample)], + [MBExample exampleWithTitle:@"With details label" selector:@selector(detailsLabelExample)]], + @[[MBExample exampleWithTitle:@"Determinate mode" selector:@selector(determinateExample)], + [MBExample exampleWithTitle:@"Annular determinate mode" selector:@selector(annularDeterminateExample)], + [MBExample exampleWithTitle:@"Bar determinate mode" selector:@selector(barDeterminateExample)]], + @[[MBExample exampleWithTitle:@"Text only" selector:@selector(textExample)], + [MBExample exampleWithTitle:@"Custom view" selector:@selector(customViewExample)], + [MBExample exampleWithTitle:@"With action button" selector:@selector(cancelationExample)], + [MBExample exampleWithTitle:@"Mode switching" selector:@selector(modeSwitchingExample)]], + @[[MBExample exampleWithTitle:@"On window" selector:@selector(indeterminateExample)], + [MBExample exampleWithTitle:@"NSURLSession" selector:@selector(networkingExample)], + [MBExample exampleWithTitle:@"Dim background" selector:@selector(indeterminateExample)], + [MBExample exampleWithTitle:@"Colored" selector:@selector(indeterminateExample)]] + ]; +} + +#pragma mark - Examples + +- (void)indeterminateExample { + // Show the HUD on the root view (self.view is a scrollable table view and thus not suitable, + // as the HUD would move with the content as we scroll). + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Fire off an asynchronous task, giving UIKit the opportunity to redraw wit the HUD added to the + // view hierarchy. + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + + // Do something useful in the background + [self doSomeWork]; + + // IMPORTANT - Dispatch back to the main thread. Always access UI + // classes (including MBProgressHUD) on the main thread. + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)labelExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the label text. + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + // You can also adjust other label properties if needed. + // hud.label.font = [UIFont italicSystemFontOfSize:16.f]; + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + [self doSomeWork]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)detailsLabelExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the label text. + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + // Set the details label text. Let's make it multiline this time. + hud.detailsLabel.text = NSLocalizedString(@"Parsing data\n(1/1)", @"HUD title"); + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + [self doSomeWork]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)windowExample { + // Covers the entire screen. Similar to using the root view controller view. + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view.window animated:YES]; + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + [self doSomeWork]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)determinateExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the determinate mode to show task progress. + hud.mode = MBProgressHUDModeDeterminate; + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + // Do something useful in the background and update the HUD periodically. + [self doSomeWorkWithProgress]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)annularDeterminateExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the annular determinate mode to show task progress. + hud.mode = MBProgressHUDModeAnnularDeterminate; + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + // Do something useful in the background and update the HUD periodically. + [self doSomeWorkWithProgress]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)barDeterminateExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the bar determinate mode to show task progress. + hud.mode = MBProgressHUDModeDeterminateHorizontalBar; + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + // Do something useful in the background and update the HUD periodically. + [self doSomeWorkWithProgress]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)customViewExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the custom view mode to show any view. + hud.mode = MBProgressHUDModeCustomView; + // Set an image view with a checkmark. + UIImage *image = [[UIImage imageNamed:@"Checkmark"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + hud.customView = [[UIImageView alloc] initWithImage:image]; + // Looks a bit nicer if we make it square. + hud.square = YES; + // Optional label text. + hud.label.text = NSLocalizedString(@"Done", @"HUD done title"); + + [hud hideAnimated:YES afterDelay:3.f]; +} + +- (void)textExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the annular determinate mode to show task progress. + hud.mode = MBProgressHUDModeText; + hud.label.text = NSLocalizedString(@"Message here!", @"HUD message title"); + // Move to bottm center. + hud.offset = CGPointMake(0.f, MBProgressMaxOffset); + + [hud hideAnimated:YES afterDelay:3.f]; +} + +- (void)cancelationExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set the determinate mode to show task progress. + hud.mode = MBProgressHUDModeDeterminate; + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + + // Configure the button. + [hud.button setTitle:NSLocalizedString(@"Cancel", @"HUD cancel button title") forState:UIControlStateNormal]; + [hud.button addTarget:self action:@selector(cancelWork:) forControlEvents:UIControlEventTouchUpInside]; + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + // Do something useful in the background and update the HUD periodically. + [self doSomeWorkWithProgress]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)modeSwitchingExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set some text to show the initial status. + hud.label.text = NSLocalizedString(@"Preparing...", @"HUD preparing title"); + // Will look best, if we set a minimum size. + hud.minSize = CGSizeMake(150.f, 100.f); + + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + // Do something useful in the background and update the HUD periodically. + [self doSomeWorkWithMixedProgress]; + dispatch_async(dispatch_get_main_queue(), ^{ + [hud hideAnimated:YES]; + }); + }); +} + +- (void)networkingExample { + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]; + + // Set some text to show the initial status. + hud.label.text = NSLocalizedString(@"Preparing...", @"HUD preparing title"); + // Will look best, if we set a minimum size. + hud.minSize = CGSizeMake(150.f, 100.f); + + [self doSomeNetworkWorkWithProgress]; +} + +#pragma mark - Tasks + +- (void)doSomeWork { + // Simulate by just waiting. + sleep(3.); +} + +- (void)doSomeWorkWithProgress { + self.canceled = NO; + // This just increases the progress indicator in a loop. + float progress = 0.0f; + while (progress < 1.0f) { + if (self.canceled) break; + progress += 0.01f; + dispatch_async(dispatch_get_main_queue(), ^{ + // Instead we could have also passed a reference to the HUD + // to the HUD to myProgressTask as a method parameter. + [MBProgressHUD HUDForView:self.navigationController.view].progress = progress; + }); + usleep(50000); + } +} + +- (void)doSomeWorkWithMixedProgress { + MBProgressHUD *hud = [MBProgressHUD HUDForView:self.navigationController.view]; + // Indeterminate mode + sleep(2); + // Switch to determinate mode + dispatch_async(dispatch_get_main_queue(), ^{ + hud.mode = MBProgressHUDModeDeterminate; + hud.label.text = NSLocalizedString(@"Loading...", @"HUD loading title"); + }); + float progress = 0.0f; + while (progress < 1.0f) { + progress += 0.01f; + dispatch_async(dispatch_get_main_queue(), ^{ + hud.progress = progress; + }); + usleep(50000); + } + // Back to indeterminate mode + dispatch_async(dispatch_get_main_queue(), ^{ + hud.mode = MBProgressHUDModeIndeterminate; + hud.label.text = NSLocalizedString(@"Cleaning up...", @"HUD cleanining up title"); + }); + sleep(2); + dispatch_sync(dispatch_get_main_queue(), ^{ + UIImage *image = [[UIImage imageNamed:@"Checkmark"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; + hud.customView = imageView; + hud.mode = MBProgressHUDModeCustomView; + hud.label.text = NSLocalizedString(@"Completed", @"HUD completed title"); + }); + sleep(2); +} + +- (void)doSomeNetworkWorkWithProgress { + NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; + NSURL *URL = [NSURL URLWithString:@"https://support.apple.com/library/APPLE/APPLECARE_ALLGEOS/HT1425/sample_iPod.m4v.zip"]; + NSURLSessionDownloadTask *task = [session downloadTaskWithURL:URL]; + [task resume]; +} + +- (void)cancelWork:(id)sender { + self.canceled = YES; +} + +#pragma mark - UITableViewDelegate + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.examples.count; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.examples[section].count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + MBExample *example = self.examples[indexPath.section][indexPath.row]; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MBExampleCell" forIndexPath:indexPath]; + cell.textLabel.text = example.title; + cell.textLabel.textColor = self.view.tintColor; + cell.textLabel.textAlignment = NSTextAlignmentCenter; + cell.selectedBackgroundView = [UIView new]; + cell.selectedBackgroundView.backgroundColor = [cell.textLabel.textColor colorWithAlphaComponent:0.1f]; + return cell; +} + +#pragma mark - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + MBExample *example = self.examples[indexPath.section][indexPath.row]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [self performSelector:example.selector]; +#pragma clang diagnostic pop + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + }); +} + +#pragma mark - NSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { + // Do something with the data at location... + + // Update the UI on the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + MBProgressHUD *hud = [MBProgressHUD HUDForView:self.navigationController.view]; + UIImage *image = [[UIImage imageNamed:@"Checkmark"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; + hud.customView = imageView; + hud.mode = MBProgressHUDModeCustomView; + hud.label.text = NSLocalizedString(@"Completed", @"HUD completed title"); + [hud hideAnimated:YES afterDelay:3.f]; + }); +} + +- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { + float progress = (float)totalBytesWritten / (float)totalBytesExpectedToWrite; + + // Update the UI on the main thread + dispatch_async(dispatch_get_main_queue(), ^{ + MBProgressHUD *hud = [MBProgressHUD HUDForView:self.navigationController.view]; + hud.mode = MBProgressHUDModeDeterminate; + hud.progress = progress; + }); +} + +@end diff --git a/Demo/HudDemo.xcodeproj/project.pbxproj b/Demo/HudDemo.xcodeproj/project.pbxproj index 2fdf39504..46034fb45 100644 --- a/Demo/HudDemo.xcodeproj/project.pbxproj +++ b/Demo/HudDemo.xcodeproj/project.pbxproj @@ -7,33 +7,21 @@ objects = { /* Begin PBXBuildFile section */ - 1D3623260D0F684500981E51 /* HudDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* HudDemoAppDelegate.m */; }; + 1D3623260D0F684500981E51 /* MBHudDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* MBHudDemoAppDelegate.m */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 28D7ACF80DDB3853001CB0EB /* HudDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* HudDemoViewController.m */; }; - D21D40801611CF6C005FCE55 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D21D407F1611CF6C005FCE55 /* Default-568h@2x.png */; }; + 28D7ACF80DDB3853001CB0EB /* MBHudDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* MBHudDemoViewController.m */; }; D22F7D810F85241C00550BB3 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = D22F7D800F85241C00550BB3 /* MBProgressHUD.m */; }; - D24A23051780ADCD0020310A /* Icon-Small.png in Resources */ = {isa = PBXBuildFile; fileRef = D22568E61780AA77008D5939 /* Icon-Small.png */; }; - D24A23061780ADD10020310A /* Icon-Small@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D22568E71780AA77008D5939 /* Icon-Small@2x.png */; }; - D24A23071780ADDA0020310A /* Icon-iOS7@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D22568E51780A9C6008D5939 /* Icon-iOS7@2x.png */; }; - D24A23081780ADE60020310A /* Default-iOS7-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D22568E31780A913008D5939 /* Default-iOS7-568h@2x.png */; }; - D24A23091780ADE90020310A /* Default-iOS7@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D22568E41780A913008D5939 /* Default-iOS7@2x.png */; }; - D277FDB311FC834200304321 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = D277FDB211FC834200304321 /* Default.png */; }; - D277FDB911FC877E00304321 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = D277FDB711FC877E00304321 /* Icon.png */; }; - D277FDBA11FC877E00304321 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D277FDB811FC877E00304321 /* Icon@2x.png */; }; - D286A6801518736B00E13FB8 /* 37x-Checkmark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D286A67F1518736B00E13FB8 /* 37x-Checkmark@2x.png */; }; - D286A7321518C53500E13FB8 /* HudDemoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D286A7341518C53500E13FB8 /* HudDemoViewController.xib */; }; - D286A7361518C53C00E13FB8 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = D286A7381518C53C00E13FB8 /* MainWindow.xib */; }; D286A76D1518CA9F00E13FB8 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D286A76C1518CA9F00E13FB8 /* CoreGraphics.framework */; }; - D28CBB321A87A45A0052DCEC /* HudTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D28CBB311A87A45A0052DCEC /* HudTests.m */; }; - D28CBB381A87A4A10052DCEC /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = D22F7D800F85241C00550BB3 /* MBProgressHUD.m */; }; - D2A6FD1D13ABC5A200BFE4C9 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D2A6FD1C13ABC5A200BFE4C9 /* Default@2x.png */; }; - D2F88CD6115E9F7F00E6DB82 /* 37x-Checkmark.png in Resources */ = {isa = PBXBuildFile; fileRef = D2F88CD5115E9F7F00E6DB82 /* 37x-Checkmark.png */; }; + D2B174121C5E3A3D00021915 /* HudTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D2B174111C5E3A3D00021915 /* HudTests.m */; }; + D2BC092F1BA587FB00589A7C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D2BC09311BA587FB00589A7C /* Main.storyboard */; }; + D2EEB37B1B558F0900F59EC1 /* Launch.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D2EEB3791B558F0900F59EC1 /* Launch.storyboard */; }; + D2EEB3811B55967200F59EC1 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D2EEB3801B55967200F59EC1 /* Images.xcassets */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - D28CBB331A87A45A0052DCEC /* PBXContainerItemProxy */ = { + D2B174141C5E3A3D00021915 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; @@ -44,35 +32,24 @@ /* Begin PBXFileReference section */ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D3623240D0F684500981E51 /* HudDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HudDemoAppDelegate.h; sourceTree = ""; }; - 1D3623250D0F684500981E51 /* HudDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HudDemoAppDelegate.m; sourceTree = ""; }; + 1D3623240D0F684500981E51 /* MBHudDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBHudDemoAppDelegate.h; sourceTree = ""; }; + 1D3623250D0F684500981E51 /* MBHudDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBHudDemoAppDelegate.m; sourceTree = ""; }; 1D6058910D05DD3D006BFB54 /* HudDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HudDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 28D7ACF60DDB3853001CB0EB /* HudDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HudDemoViewController.h; sourceTree = ""; }; - 28D7ACF70DDB3853001CB0EB /* HudDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HudDemoViewController.m; sourceTree = ""; usesTabs = 1; }; + 28D7ACF60DDB3853001CB0EB /* MBHudDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBHudDemoViewController.h; sourceTree = ""; }; + 28D7ACF70DDB3853001CB0EB /* MBHudDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBHudDemoViewController.m; sourceTree = ""; usesTabs = 1; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32CA4F630368D1EE00C91783 /* HudDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HudDemo_Prefix.pch; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D21D407F1611CF6C005FCE55 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "Images/Default-568h@2x.png"; sourceTree = ""; }; - D22568E31780A913008D5939 /* Default-iOS7-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-iOS7-568h@2x.png"; path = "Images/Default-iOS7-568h@2x.png"; sourceTree = ""; }; - D22568E41780A913008D5939 /* Default-iOS7@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-iOS7@2x.png"; path = "Images/Default-iOS7@2x.png"; sourceTree = ""; }; - D22568E51780A9C6008D5939 /* Icon-iOS7@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon-iOS7@2x.png"; path = "Images/Icon-iOS7@2x.png"; sourceTree = ""; }; - D22568E61780AA77008D5939 /* Icon-Small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon-Small.png"; path = "Images/Icon-Small.png"; sourceTree = ""; }; - D22568E71780AA77008D5939 /* Icon-Small@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon-Small@2x.png"; path = "Images/Icon-Small@2x.png"; sourceTree = ""; }; D22F7D7F0F85241C00550BB3 /* MBProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MBProgressHUD.h; path = ../MBProgressHUD.h; sourceTree = SOURCE_ROOT; }; D22F7D800F85241C00550BB3 /* MBProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MBProgressHUD.m; path = ../MBProgressHUD.m; sourceTree = ""; }; - D277FDB211FC834200304321 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Images/Default.png; sourceTree = ""; }; - D277FDB711FC877E00304321 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon.png; path = Images/Icon.png; sourceTree = ""; }; - D277FDB811FC877E00304321 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Icon@2x.png"; path = "Images/Icon@2x.png"; sourceTree = ""; }; - D286A67F1518736B00E13FB8 /* 37x-Checkmark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "37x-Checkmark@2x.png"; path = "Images/37x-Checkmark@2x.png"; sourceTree = ""; }; - D286A7331518C53500E13FB8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/HudDemoViewController.xib; sourceTree = ""; }; - D286A7371518C53C00E13FB8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow.xib; sourceTree = ""; }; D286A76C1518CA9F00E13FB8 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - D28CBB2D1A87A45A0052DCEC /* HudTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HudTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - D28CBB301A87A45A0052DCEC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D28CBB311A87A45A0052DCEC /* HudTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HudTests.m; sourceTree = ""; }; - D2A6FD1C13ABC5A200BFE4C9 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Images/Default@2x.png"; sourceTree = ""; }; - D2F88CD5115E9F7F00E6DB82 /* 37x-Checkmark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "37x-Checkmark.png"; path = "Images/37x-Checkmark.png"; sourceTree = ""; }; + D2B1740F1C5E3A3D00021915 /* HudTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HudTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D2B174111C5E3A3D00021915 /* HudTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HudTests.m; sourceTree = ""; }; + D2B174131C5E3A3D00021915 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D2BC09301BA587FB00589A7C /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Main.storyboard; sourceTree = ""; }; + D2EEB37A1B558F0900F59EC1 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Launch.storyboard; sourceTree = ""; }; + D2EEB3801B55967200F59EC1 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = HudDemo/Images.xcassets; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -86,7 +63,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - D28CBB2A1A87A45A0052DCEC /* Frameworks */ = { + D2B1740C1C5E3A3D00021915 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -99,10 +76,10 @@ 080E96DDFE201D6D7F000001 /* HudDemo */ = { isa = PBXGroup; children = ( - 1D3623240D0F684500981E51 /* HudDemoAppDelegate.h */, - 1D3623250D0F684500981E51 /* HudDemoAppDelegate.m */, - 28D7ACF60DDB3853001CB0EB /* HudDemoViewController.h */, - 28D7ACF70DDB3853001CB0EB /* HudDemoViewController.m */, + 1D3623240D0F684500981E51 /* MBHudDemoAppDelegate.h */, + 1D3623250D0F684500981E51 /* MBHudDemoAppDelegate.m */, + 28D7ACF60DDB3853001CB0EB /* MBHudDemoViewController.h */, + 28D7ACF70DDB3853001CB0EB /* MBHudDemoViewController.m */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, ); @@ -114,7 +91,7 @@ isa = PBXGroup; children = ( 1D6058910D05DD3D006BFB54 /* HudDemo.app */, - D28CBB2D1A87A45A0052DCEC /* HudTests.xctest */, + D2B1740F1C5E3A3D00021915 /* HudTests.xctest */, ); name = Products; sourceTree = ""; @@ -123,7 +100,7 @@ isa = PBXGroup; children = ( 080E96DDFE201D6D7F000001 /* HudDemo */, - D28CBB2E1A87A45A0052DCEC /* HudTests */, + D2B174101C5E3A3D00021915 /* HudTests */, D28CBB391A87A6B00052DCEC /* MBProgressHUD */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, @@ -145,7 +122,7 @@ isa = PBXGroup; children = ( D277FDBF11FC880100304321 /* UI */, - D277FDBD11FC879500304321 /* Images */, + D2EEB3801B55967200F59EC1 /* Images.xcassets */, 8D1107310486CEB800E47090 /* Info.plist */, ); name = Resources; @@ -162,58 +139,31 @@ name = Frameworks; sourceTree = ""; }; - D277FDBD11FC879500304321 /* Images */ = { - isa = PBXGroup; - children = ( - D277FDB711FC877E00304321 /* Icon.png */, - D277FDB811FC877E00304321 /* Icon@2x.png */, - D22568E61780AA77008D5939 /* Icon-Small.png */, - D22568E71780AA77008D5939 /* Icon-Small@2x.png */, - D22568E51780A9C6008D5939 /* Icon-iOS7@2x.png */, - D277FDB211FC834200304321 /* Default.png */, - D2A6FD1C13ABC5A200BFE4C9 /* Default@2x.png */, - D21D407F1611CF6C005FCE55 /* Default-568h@2x.png */, - D22568E31780A913008D5939 /* Default-iOS7-568h@2x.png */, - D22568E41780A913008D5939 /* Default-iOS7@2x.png */, - D2F88CD5115E9F7F00E6DB82 /* 37x-Checkmark.png */, - D286A67F1518736B00E13FB8 /* 37x-Checkmark@2x.png */, - ); - name = Images; - sourceTree = ""; - }; D277FDBF11FC880100304321 /* UI */ = { isa = PBXGroup; children = ( - D286A7341518C53500E13FB8 /* HudDemoViewController.xib */, - D286A7381518C53C00E13FB8 /* MainWindow.xib */, + D2EEB3791B558F0900F59EC1 /* Launch.storyboard */, + D2BC09311BA587FB00589A7C /* Main.storyboard */, ); name = UI; sourceTree = ""; }; - D28CBB2E1A87A45A0052DCEC /* HudTests */ = { + D28CBB391A87A6B00052DCEC /* MBProgressHUD */ = { isa = PBXGroup; children = ( - D28CBB311A87A45A0052DCEC /* HudTests.m */, - D28CBB2F1A87A45A0052DCEC /* Supporting Files */, + D22F7D7F0F85241C00550BB3 /* MBProgressHUD.h */, + D22F7D800F85241C00550BB3 /* MBProgressHUD.m */, ); - path = HudTests; + name = MBProgressHUD; sourceTree = ""; }; - D28CBB2F1A87A45A0052DCEC /* Supporting Files */ = { + D2B174101C5E3A3D00021915 /* HudTests */ = { isa = PBXGroup; children = ( - D28CBB301A87A45A0052DCEC /* Info.plist */, + D2B174111C5E3A3D00021915 /* HudTests.m */, + D2B174131C5E3A3D00021915 /* Info.plist */, ); - name = "Supporting Files"; - sourceTree = ""; - }; - D28CBB391A87A6B00052DCEC /* MBProgressHUD */ = { - isa = PBXGroup; - children = ( - D22F7D7F0F85241C00550BB3 /* MBProgressHUD.h */, - D22F7D800F85241C00550BB3 /* MBProgressHUD.m */, - ); - name = MBProgressHUD; + path = HudTests; sourceTree = ""; }; /* End PBXGroup section */ @@ -236,22 +186,22 @@ productReference = 1D6058910D05DD3D006BFB54 /* HudDemo.app */; productType = "com.apple.product-type.application"; }; - D28CBB2C1A87A45A0052DCEC /* HudTests */ = { + D2B1740E1C5E3A3D00021915 /* HudTests */ = { isa = PBXNativeTarget; - buildConfigurationList = D28CBB351A87A45A0052DCEC /* Build configuration list for PBXNativeTarget "HudTests" */; + buildConfigurationList = D2B174161C5E3A3D00021915 /* Build configuration list for PBXNativeTarget "HudTests" */; buildPhases = ( - D28CBB291A87A45A0052DCEC /* Sources */, - D28CBB2A1A87A45A0052DCEC /* Frameworks */, - D28CBB2B1A87A45A0052DCEC /* Resources */, + D2B1740B1C5E3A3D00021915 /* Sources */, + D2B1740C1C5E3A3D00021915 /* Frameworks */, + D2B1740D1C5E3A3D00021915 /* Resources */, ); buildRules = ( ); dependencies = ( - D28CBB341A87A45A0052DCEC /* PBXTargetDependency */, + D2B174151C5E3A3D00021915 /* PBXTargetDependency */, ); name = HudTests; productName = HudTests; - productReference = D28CBB2D1A87A45A0052DCEC /* HudTests.xctest */; + productReference = D2B1740F1C5E3A3D00021915 /* HudTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -261,11 +211,11 @@ isa = PBXProject; attributes = { CLASSPREFIX = MB; - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Matej Bukovinski"; TargetAttributes = { - D28CBB2C1A87A45A0052DCEC = { - CreatedOnToolsVersion = 6.1.1; + D2B1740E1C5E3A3D00021915 = { + CreatedOnToolsVersion = 7.2; TestTargetID = 1D6058900D05DD3D006BFB54; }; }; @@ -279,13 +229,14 @@ Japanese, French, German, + en, ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; targets = ( 1D6058900D05DD3D006BFB54 /* HudDemo */, - D28CBB2C1A87A45A0052DCEC /* HudTests */, + D2B1740E1C5E3A3D00021915 /* HudTests */, ); }; /* End PBXProject section */ @@ -295,24 +246,13 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - D286A7361518C53C00E13FB8 /* MainWindow.xib in Resources */, - D286A7321518C53500E13FB8 /* HudDemoViewController.xib in Resources */, - D2F88CD6115E9F7F00E6DB82 /* 37x-Checkmark.png in Resources */, - D277FDB311FC834200304321 /* Default.png in Resources */, - D277FDB911FC877E00304321 /* Icon.png in Resources */, - D277FDBA11FC877E00304321 /* Icon@2x.png in Resources */, - D2A6FD1D13ABC5A200BFE4C9 /* Default@2x.png in Resources */, - D286A6801518736B00E13FB8 /* 37x-Checkmark@2x.png in Resources */, - D24A23081780ADE60020310A /* Default-iOS7-568h@2x.png in Resources */, - D24A23051780ADCD0020310A /* Icon-Small.png in Resources */, - D24A23071780ADDA0020310A /* Icon-iOS7@2x.png in Resources */, - D21D40801611CF6C005FCE55 /* Default-568h@2x.png in Resources */, - D24A23061780ADD10020310A /* Icon-Small@2x.png in Resources */, - D24A23091780ADE90020310A /* Default-iOS7@2x.png in Resources */, + D2BC092F1BA587FB00589A7C /* Main.storyboard in Resources */, + D2EEB3811B55967200F59EC1 /* Images.xcassets in Resources */, + D2EEB37B1B558F0900F59EC1 /* Launch.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - D28CBB2B1A87A45A0052DCEC /* Resources */ = { + D2B1740D1C5E3A3D00021915 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -327,46 +267,45 @@ buildActionMask = 2147483647; files = ( 1D60589B0D05DD56006BFB54 /* main.m in Sources */, - 1D3623260D0F684500981E51 /* HudDemoAppDelegate.m in Sources */, - 28D7ACF80DDB3853001CB0EB /* HudDemoViewController.m in Sources */, + 1D3623260D0F684500981E51 /* MBHudDemoAppDelegate.m in Sources */, + 28D7ACF80DDB3853001CB0EB /* MBHudDemoViewController.m in Sources */, D22F7D810F85241C00550BB3 /* MBProgressHUD.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - D28CBB291A87A45A0052DCEC /* Sources */ = { + D2B1740B1C5E3A3D00021915 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D28CBB321A87A45A0052DCEC /* HudTests.m in Sources */, - D28CBB381A87A4A10052DCEC /* MBProgressHUD.m in Sources */, + D2B174121C5E3A3D00021915 /* HudTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - D28CBB341A87A45A0052DCEC /* PBXTargetDependency */ = { + D2B174151C5E3A3D00021915 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1D6058900D05DD3D006BFB54 /* HudDemo */; - targetProxy = D28CBB331A87A45A0052DCEC /* PBXContainerItemProxy */; + targetProxy = D2B174141C5E3A3D00021915 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - D286A7341518C53500E13FB8 /* HudDemoViewController.xib */ = { + D2BC09311BA587FB00589A7C /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( - D286A7331518C53500E13FB8 /* en */, + D2BC09301BA587FB00589A7C /* en */, ); - name = HudDemoViewController.xib; + name = Main.storyboard; sourceTree = ""; }; - D286A7381518C53C00E13FB8 /* MainWindow.xib */ = { + D2EEB3791B558F0900F59EC1 /* Launch.storyboard */ = { isa = PBXVariantGroup; children = ( - D286A7371518C53C00E13FB8 /* en */, + D2EEB37A1B558F0900F59EC1 /* en */, ); - name = MainWindow.xib; + name = Launch.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ @@ -376,12 +315,15 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = HudDemo_Prefix.pch; INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.bukovinski.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = HudDemo; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -391,10 +333,13 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = HudDemo_Prefix.pch; INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.bukovinski.${PRODUCT_NAME:identifier}"; PRODUCT_NAME = HudDemo; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -404,6 +349,7 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -413,6 +359,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_NO_COMMON_BLOCKS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; @@ -422,7 +369,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; @@ -431,6 +378,7 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -449,12 +397,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; SDKROOT = iphoneos; }; name = Release; }; - D28CBB361A87A45A0052DCEC /* Debug */ = { + D2B174171C5E3A3D00021915 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -462,14 +410,10 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); + DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -477,19 +421,19 @@ "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = HudTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.bukovinski.HudTests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HudDemo.app/HudDemo"; }; name = Debug; }; - D28CBB371A87A45A0052DCEC /* Release */ = { + D2B174181C5E3A3D00021915 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -497,22 +441,19 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - COPY_PHASE_STRIP = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = HudTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.bukovinski.HudTests; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HudDemo.app/HudDemo"; VALIDATE_PRODUCT = YES; @@ -540,14 +481,13 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D28CBB351A87A45A0052DCEC /* Build configuration list for PBXNativeTarget "HudTests" */ = { + D2B174161C5E3A3D00021915 /* Build configuration list for PBXNativeTarget "HudTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - D28CBB361A87A45A0052DCEC /* Debug */, - D28CBB371A87A45A0052DCEC /* Release */, + D2B174171C5E3A3D00021915 /* Debug */, + D2B174181C5E3A3D00021915 /* Release */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudDemo.xcscheme b/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudDemo.xcscheme index 3e25c0eea..36992107c 100644 --- a/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudDemo.xcscheme +++ b/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudDemo.xcscheme @@ -1,6 +1,6 @@ @@ -37,21 +37,11 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + @@ -90,10 +83,10 @@ diff --git a/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudTests.xcscheme b/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudTests.xcscheme new file mode 100644 index 000000000..9ecd5ba5f --- /dev/null +++ b/Demo/HudDemo.xcodeproj/xcshareddata/xcschemes/HudTests.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..7110beb82 --- /dev/null +++ b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,128 @@ +{ + "images" : [ + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Small.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Small@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Small@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@3x.png", + "scale" : "3x" + }, + { + "size" : "57x57", + "idiom" : "iphone", + "filename" : "Icon.png", + "scale" : "1x" + }, + { + "size" : "57x57", + "idiom" : "iphone", + "filename" : "Icon@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-Small-1.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-Small@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-Small-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-Small-40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "50x50", + "idiom" : "ipad", + "filename" : "Icon-Small-50.png", + "scale" : "1x" + }, + { + "size" : "50x50", + "idiom" : "ipad", + "filename" : "Icon-Small-50@2x.png", + "scale" : "2x" + }, + { + "size" : "72x72", + "idiom" : "ipad", + "filename" : "Icon-72.png", + "scale" : "1x" + }, + { + "size" : "72x72", + "idiom" : "ipad", + "filename" : "Icon-72@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-167.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-167.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-167.png new file mode 100644 index 000000000..428429944 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-167.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png new file mode 100644 index 000000000..2190fcf5d Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100644 index 000000000..f45eb2876 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-72.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-72.png new file mode 100644 index 000000000..ef7c3d72a Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-72.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png new file mode 100644 index 000000000..d6c4d7eb4 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-76.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100644 index 000000000..a6486b765 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png new file mode 100644 index 000000000..f415127d6 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png new file mode 100644 index 000000000..9fa153185 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png new file mode 100644 index 000000000..76d2ac5d1 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png new file mode 100644 index 000000000..0e27276f1 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png new file mode 100644 index 000000000..0e27276f1 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png new file mode 100644 index 000000000..4f32b2d97 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png new file mode 100644 index 000000000..b4294c24c Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png new file mode 100644 index 000000000..835ec95b4 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small.png new file mode 100644 index 000000000..9fa153185 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png new file mode 100644 index 000000000..d5fda5641 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png new file mode 100644 index 000000000..d5fda5641 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png new file mode 100644 index 000000000..ffc2b3cc8 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon.png new file mode 100644 index 000000000..ddb24a93b Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon.png differ diff --git a/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon@2x.png b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon@2x.png new file mode 100644 index 000000000..32bf64549 Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/AppIcon.appiconset/Icon@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark.png b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark.png new file mode 100644 index 000000000..c94cdd75d Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark.png differ diff --git a/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark@2x.png b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark@2x.png new file mode 100644 index 000000000..49639641b Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark@2x.png differ diff --git a/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark@3x.png b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark@3x.png new file mode 100644 index 000000000..03586285c Binary files /dev/null and b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Checkmark@3x.png differ diff --git a/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Contents.json b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Contents.json new file mode 100644 index 000000000..eee4cee8e --- /dev/null +++ b/Demo/HudDemo/Images.xcassets/Checkmark.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Checkmark.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Checkmark@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Checkmark@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Demo/HudDemo/Images.xcassets/Contents.json b/Demo/HudDemo/Images.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/Demo/HudDemo/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Demo/HudTests/HudTests.m b/Demo/HudTests/HudTests.m index 04cd00655..33653bbcc 100644 --- a/Demo/HudTests/HudTests.m +++ b/Demo/HudTests/HudTests.m @@ -2,41 +2,116 @@ // HudTests.m // HudTests // -// Created by Matej Bukovinski on 8. 02. 15. -// Copyright (c) 2015 Matej Bukovinski. All rights reserved. +// Created by Matej Bukovinski on 31. 01. 16. +// Copyright © 2016 Matej Bukovinski. All rights reserved. // -#import #import #import "MBProgressHUD.h" -@interface HudTests : XCTestCase +#define weakify(var) __weak typeof(var) weak_##var = var; -@property (nonatomic, strong) MBProgressHUD *hud; -@property (nonatomic, strong) UIView *view; +#define strongify(var) \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wshadow\"") \ +__strong typeof(var) var = weak_##var; \ +_Pragma("clang diagnostic pop") + + +@interface HudTests : XCTestCase + +@property (nonatomic) XCTestExpectation *hideExpectation; +@property (nonatomic, copy) dispatch_block_t hideChecks; @end + @implementation HudTests - (void)setUp { [super setUp]; - - self.view = [[UIView alloc] init]; - self.view.bounds = [[UIScreen mainScreen] bounds]; - self.hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; } - (void)tearDown { - self.hud = nil; - self.view = nil; - [super tearDown]; } -- (void)testThatHUDExists { - XCTAssertNotNil(self.hud, @"Should be able to create a new HUD instance"); +#pragma mark - Convenience + +- (void)testNonAnimatedConvenienceHUDPresentation { + UIViewController *rootViewController = UIApplication.sharedApplication.keyWindow.rootViewController; + UIView *rootView = rootViewController.view; + + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:rootView animated:NO]; + + XCTAssertNotNil(hud, @"A HUD should be created."); + XCTAssertEqualObjects(hud.superview, rootView, @"The hood should be added to the view."); + XCTAssertTrue(hud.removeFromSuperViewOnHide, @"removeFromSuperViewOnHide should be enabled"); + XCTAssertEqual(hud.alpha, 1.f, @"The HUD should be visible."); + XCTAssertFalse(hud.hidden, @"The HUD should be visible."); + + XCTAssertEqual(hud.bezelView.alpha, 1.f, @"The HUD should be visible."); + XCTAssertFalse([hud.bezelView.layer.animationKeys containsObject:@"opacity"], @"The opacity should NOT be animated."); + + XCTAssertEqualObjects([MBProgressHUD HUDForView:rootView], hud, @"The HUD should be found via the convenience operation."); + + XCTAssertTrue([MBProgressHUD hideHUDForView:rootView animated:NO], @"The HUD should be found and removed."); + + XCTAssertFalse([rootView.subviews containsObject:hud], @"The HUD should no longer be part of the view hierarchy."); + XCTAssertEqual(hud.alpha, 0.f, @"The hud should be faded out."); + XCTAssertNil(hud.superview, @"The HUD should no longer be part of the view hierarchy."); + + XCTAssertFalse([MBProgressHUD hideHUDForView:rootView animated:NO], @"A subsequent HUD hide operation should fail."); +} + +- (void)testAnimatedConvenienceHUDPresentation { + UIViewController *rootViewController = UIApplication.sharedApplication.keyWindow.rootViewController; + UIView *rootView = rootViewController.view; + + self.hideExpectation = [self expectationWithDescription:@"The hudWasHidden: delegate should have been called."]; + + MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:rootView animated:YES]; + hud.delegate = self; + + XCTAssertNotNil(hud, @"A HUD should be created."); + XCTAssertEqualObjects(hud.superview, rootView, @"The hood should be added to the view."); + XCTAssertTrue(hud.removeFromSuperViewOnHide, @"removeFromSuperViewOnHide should be enabled"); + XCTAssertEqual(hud.alpha, 1.f, @"The HUD should be visible."); + XCTAssertFalse(hud.hidden, @"The HUD should be visible."); + + XCTAssertEqual(hud.bezelView.alpha, 1.f, @"The HUD should be visible."); + XCTAssertTrue([hud.bezelView.layer.animationKeys containsObject:@"opacity"], @"The opacity should be animated."); + + XCTAssertEqualObjects([MBProgressHUD HUDForView:rootView], hud, @"The HUD should be found via the convenience operation."); + + XCTAssertTrue([MBProgressHUD hideHUDForView:rootView animated:YES], @"The HUD should be found and removed."); + + XCTAssertTrue([rootView.subviews containsObject:hud], @"The HUD should still be part of the view hierarchy."); + XCTAssertEqual(hud.alpha, 1.f, @"The hud should still be visible."); + XCTAssertEqualObjects(hud.superview, rootView, @"The hood should be added to the view."); + + weakify(self); + self.hideChecks = ^{ + strongify(self); + XCTAssertFalse([rootView.subviews containsObject:hud], @"The HUD should no longer be part of the view hierarchy."); + XCTAssertEqual(hud.alpha, 0.f, @"The hud should be faded out."); + XCTAssertNil(hud.superview, @"The HUD should no longer be part of the view hierarchy."); + + XCTAssertFalse([MBProgressHUD hideHUDForView:rootView animated:YES], @"A subsequent HUD hide operation should fail."); + }; + + [self waitForExpectationsWithTimeout:5. handler:nil]; +} + +#pragma mark - MBProgressHUDDelegate + +- (void)hudWasHidden:(MBProgressHUD *)hud { + if (self.hideChecks) self.hideChecks(); + self.hideChecks = nil; + + [self.hideExpectation fulfill]; + self.hideExpectation = nil; } @end diff --git a/Demo/HudTests/Info.plist b/Demo/HudTests/Info.plist index fc755afa6..ba72822e8 100644 --- a/Demo/HudTests/Info.plist +++ b/Demo/HudTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.bukovinski.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Demo/Images/37x-Checkmark.png b/Demo/Images/37x-Checkmark.png deleted file mode 100644 index f330b70ad..000000000 Binary files a/Demo/Images/37x-Checkmark.png and /dev/null differ diff --git a/Demo/Images/37x-Checkmark@2x.png b/Demo/Images/37x-Checkmark@2x.png deleted file mode 100644 index 2cb680b53..000000000 Binary files a/Demo/Images/37x-Checkmark@2x.png and /dev/null differ diff --git a/Demo/Images/Default-568h@2x.png b/Demo/Images/Default-568h@2x.png deleted file mode 100644 index d2d6399aa..000000000 Binary files a/Demo/Images/Default-568h@2x.png and /dev/null differ diff --git a/Demo/Images/Default-iOS7-568h@2x.png b/Demo/Images/Default-iOS7-568h@2x.png deleted file mode 100644 index c1e1623b7..000000000 Binary files a/Demo/Images/Default-iOS7-568h@2x.png and /dev/null differ diff --git a/Demo/Images/Default-iOS7@2x.png b/Demo/Images/Default-iOS7@2x.png deleted file mode 100644 index 0284c8174..000000000 Binary files a/Demo/Images/Default-iOS7@2x.png and /dev/null differ diff --git a/Demo/Images/Default.png b/Demo/Images/Default.png deleted file mode 100644 index 4c28122ac..000000000 Binary files a/Demo/Images/Default.png and /dev/null differ diff --git a/Demo/Images/Default@2x.png b/Demo/Images/Default@2x.png deleted file mode 100644 index 78c7125c5..000000000 Binary files a/Demo/Images/Default@2x.png and /dev/null differ diff --git a/Demo/Images/Icon-Small.png b/Demo/Images/Icon-Small.png deleted file mode 100644 index d840cc5ff..000000000 Binary files a/Demo/Images/Icon-Small.png and /dev/null differ diff --git a/Demo/Images/Icon-Small@2x.png b/Demo/Images/Icon-Small@2x.png deleted file mode 100644 index c6de46def..000000000 Binary files a/Demo/Images/Icon-Small@2x.png and /dev/null differ diff --git a/Demo/Images/Icon-iOS7@2x.png b/Demo/Images/Icon-iOS7@2x.png deleted file mode 100644 index 07040fca4..000000000 Binary files a/Demo/Images/Icon-iOS7@2x.png and /dev/null differ diff --git a/Demo/Images/Icon.png b/Demo/Images/Icon.png deleted file mode 100644 index 430cb6c27..000000000 Binary files a/Demo/Images/Icon.png and /dev/null differ diff --git a/Demo/Images/Icon@2x.png b/Demo/Images/Icon@2x.png deleted file mode 100644 index 68d2e0bef..000000000 Binary files a/Demo/Images/Icon@2x.png and /dev/null differ diff --git a/Demo/Info.plist b/Demo/Info.plist index bbbffe1fc..d11b218f8 100644 --- a/Demo/Info.plist +++ b/Demo/Info.plist @@ -8,17 +8,12 @@ ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIconFiles - - Icon-Small - Icon-iOS7 - Icon.png - Icon@2x.png - + CFBundleIcons + + CFBundleIcons~ipad + CFBundleIdentifier - com.bukovinski.${PRODUCT_NAME:identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -33,8 +28,6 @@ 1.0 LSRequiresIPhoneOS - NSMainNibFile - MainWindow UILaunchImages @@ -59,7 +52,9 @@ UILaunchStoryboardName - MainWindow + Launch + UIMainStoryboardFile + Main UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/Demo/en.lproj/HudDemoViewController.xib b/Demo/en.lproj/HudDemoViewController.xib deleted file mode 100644 index 6a4d1a365..000000000 --- a/Demo/en.lproj/HudDemoViewController.xib +++ /dev/null @@ -1,269 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Demo/en.lproj/Launch.storyboard b/Demo/en.lproj/Launch.storyboard new file mode 100644 index 000000000..d232745a9 --- /dev/null +++ b/Demo/en.lproj/Launch.storyboard @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/en.lproj/Main.storyboard b/Demo/en.lproj/Main.storyboard new file mode 100644 index 000000000..ce0a44e20 --- /dev/null +++ b/Demo/en.lproj/Main.storyboard @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo/en.lproj/MainWindow.xib b/Demo/en.lproj/MainWindow.xib deleted file mode 100644 index dffe5065e..000000000 --- a/Demo/en.lproj/MainWindow.xib +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Demo/main.m b/Demo/main.m index fd8b665eb..ef3472167 100644 --- a/Demo/main.m +++ b/Demo/main.m @@ -3,15 +3,14 @@ // HudDemo // // Created by Matej Bukovinski on 2.4.09. -// Copyright bukovinski.com 2009. All rights reserved. +// Copyright bukovinski.com 2009-2015. All rights reserved. // #import +#import "MBHudDemoAppDelegate.h" int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - NSInteger retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([MBHudDemoAppDelegate class])); + } } diff --git a/Framework-Info.plist b/Framework-Info.plist new file mode 100644 index 000000000..d3de8eefb --- /dev/null +++ b/Framework-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/MBProgressHUD.h b/MBProgressHUD.h index 433c56b71..964d41fec 100644 --- a/MBProgressHUD.h +++ b/MBProgressHUD.h @@ -1,6 +1,6 @@ // // MBProgressHUD.h -// Version 0.9.1 +// Version 0.9.2 // Created by Matej Bukovinski on 2.4.09. // @@ -30,90 +30,65 @@ #import #import +@class MBBackgroundView; @protocol MBProgressHUDDelegate; +extern CGFloat const MBProgressMaxOffset; + typedef NS_ENUM(NSInteger, MBProgressHUDMode) { - /** Progress is shown using an UIActivityIndicatorView. This is the default. */ - MBProgressHUDModeIndeterminate, - /** Progress is shown using a round, pie-chart like, progress view. */ - MBProgressHUDModeDeterminate, - /** Progress is shown using a horizontal progress bar */ - MBProgressHUDModeDeterminateHorizontalBar, - /** Progress is shown using a ring-shaped progress view. */ - MBProgressHUDModeAnnularDeterminate, - /** Shows a custom view */ - MBProgressHUDModeCustomView, - /** Shows only labels */ - MBProgressHUDModeText + /// UIActivityIndicatorView. + MBProgressHUDModeIndeterminate, + /// A round, pie-chart like, progress view. + MBProgressHUDModeDeterminate, + /// Horizontal progress bar. + MBProgressHUDModeDeterminateHorizontalBar, + /// Ring-shaped progress view. + MBProgressHUDModeAnnularDeterminate, + /// Shows a custom view. + MBProgressHUDModeCustomView, + /// Shows only labels. + MBProgressHUDModeText }; typedef NS_ENUM(NSInteger, MBProgressHUDAnimation) { - /** Opacity animation */ - MBProgressHUDAnimationFade, - /** Opacity + scale animation */ - MBProgressHUDAnimationZoom, - MBProgressHUDAnimationZoomOut = MBProgressHUDAnimationZoom, - MBProgressHUDAnimationZoomIn + /// Opacity animation + MBProgressHUDAnimationFade, + /// Opacity + scale animation (zoom in when appearing zoom out when disappearing) + MBProgressHUDAnimationZoom, + /// Opacity + scale animation (zoom out style) + MBProgressHUDAnimationZoomOut, + /// Opacity + scale animation (zoom in style) + MBProgressHUDAnimationZoomIn +}; + +typedef NS_ENUM(NSInteger, MBProgressHUDBackgroundStyle) { + /// Solid color background + MBProgressHUDBackgroundStyleSolidColor, + /// UIVisualEffectView or UIToolbar.layer background view + MBProgressHUDBackgroundStyleBlur }; -#ifndef MB_INSTANCETYPE -#if __has_feature(objc_instancetype) - #define MB_INSTANCETYPE instancetype -#else - #define MB_INSTANCETYPE id -#endif -#endif - -#ifndef MB_STRONG -#if __has_feature(objc_arc) - #define MB_STRONG strong -#else - #define MB_STRONG retain -#endif -#endif - -#ifndef MB_WEAK -#if __has_feature(objc_arc_weak) - #define MB_WEAK weak -#elif __has_feature(objc_arc) - #define MB_WEAK unsafe_unretained -#else - #define MB_WEAK assign -#endif -#endif - -#if NS_BLOCKS_AVAILABLE -typedef void (^MBProgressHUDCompletionBlock)(); -#endif +NS_ASSUME_NONNULL_BEGIN /** * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. * * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. - * The MBProgressHUD window spans over the entire space given to it by the initWithFrame constructor and catches all - * user input on this region, thereby preventing the user operations on components below the view. The HUD itself is - * drawn centered as a rounded semi-transparent view which resizes depending on the user specified content. + * The MBProgressHUD window spans over the entire space given to it by the initWithFrame: constructor and catches all + * user input on this region, thereby preventing the user operations on components below the view. * - * This view supports four modes of operation: - * - MBProgressHUDModeIndeterminate - shows a UIActivityIndicatorView - * - MBProgressHUDModeDeterminate - shows a custom round progress indicator - * - MBProgressHUDModeAnnularDeterminate - shows a custom annular progress indicator - * - MBProgressHUDModeCustomView - shows an arbitrary, user specified view (see `customView`) - * - * All three modes can have optional labels assigned: - * - If the labelText property is set and non-empty then a label containing the provided content is placed below the - * indicator view. - * - If also the detailsLabelText property is set then another label is placed below the first label. + * @note To still allow touches to pass through the HUD, you can set hud.userInteractionEnabled = NO. + * @attention MBProgressHUD is a UI class and should therefore only be accessed on the main thread. */ @interface MBProgressHUD : UIView /** * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. * - * @note This method sets `removeFromSuperViewOnHide`. The HUD will automatically be removed from the view hierarchy when hidden. + * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. * * @param view The view that the HUD will be added to * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use @@ -123,7 +98,9 @@ typedef void (^MBProgressHUDCompletionBlock)(); * @see hideHUDForView:animated: * @see animationType */ -+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; ++ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; + +/// @name Showing and hiding /** * Finds the top-most HUD subview and hides it. The counterpart to this method is showHUDAddedTo:animated:. @@ -140,45 +117,13 @@ typedef void (^MBProgressHUDCompletionBlock)(); */ + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; -/** - * Finds all the HUD subviews and hides them. - * - * @note This method sets `removeFromSuperViewOnHide`. The HUDs will automatically be removed from the view hierarchy when hidden. - * - * @param view The view that is going to be searched for HUD subviews. - * @param animated If set to YES the HUDs will disappear using the current animationType. If set to NO the HUDs will not use - * animations while disappearing. - * @return the number of HUDs found and removed. - * - * @see hideHUDForView:animated: - * @see animationType - */ -+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated; - /** * Finds the top-most HUD subview and returns it. * * @param view The view that is going to be searched. * @return A reference to the last HUD subview discovered. */ -+ (MB_INSTANCETYPE)HUDForView:(UIView *)view; - -/** - * Finds all HUD subviews and returns them. - * - * @param view The view that is going to be searched. - * @return All found HUD views (array of MBProgressHUD objects). - */ -+ (NSArray *)allHUDsForView:(UIView *)view; - -/** - * A convenience constructor that initializes the HUD with the window's bounds. Calls the designated constructor with - * window.bounds as the parameter. - * - * @param window The window instance that will provide the bounds for the HUD. Should be the same instance as - * the HUD's superview (i.e., the window that the HUD will be added to). - */ -- (id)initWithWindow:(UIWindow *)window; ++ (nullable MBProgressHUD *)HUDForView:(UIView *)view; /** * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with @@ -187,10 +132,12 @@ typedef void (^MBProgressHUDCompletionBlock)(); * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as * the HUD's superview (i.e., the view that the HUD will be added to). */ -- (id)initWithView:(UIView *)view; +- (instancetype)initWithView:(UIView *)view; /** - * Display the HUD. You need to make sure that the main thread completes its run loop soon after this method call so + * Displays the HUD. + * + * @note You need to make sure that the main thread completes its run loop soon after this method call so * the user interface can be updated. Call this method when your task is already set-up to be executed in a new thread * (e.g., when using something like NSOperation or calling an asynchronous call like NSURLRequest). * @@ -199,10 +146,10 @@ typedef void (^MBProgressHUDCompletionBlock)(); * * @see animationType */ -- (void)show:(BOOL)animated; +- (void)showAnimated:(BOOL)animated; /** - * Hide the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to + * Hides the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to * hide the HUD when your task completes. * * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use @@ -210,10 +157,10 @@ typedef void (^MBProgressHUDCompletionBlock)(); * * @see animationType */ -- (void)hide:(BOOL)animated; +- (void)hideAnimated:(BOOL)animated; /** - * Hide the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to + * Hides the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to * hide the HUD when your task completes. * * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use @@ -222,231 +169,124 @@ typedef void (^MBProgressHUDCompletionBlock)(); * * @see animationType */ -- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay; - -/** - * Shows the HUD while a background task is executing in a new thread, then hides the HUD. - * - * This method also takes care of autorelease pools so your method does not have to be concerned with setting up a - * pool. - * - * @param method The method to be executed while the HUD is shown. This method will be executed in a new thread. - * @param target The object that the target method belongs to. - * @param object An optional object to be passed to the method. - * @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will not use - * animations while (dis)appearing. - */ -- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated; - -#if NS_BLOCKS_AVAILABLE +- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; /** - * Shows the HUD while a block is executing on a background queue, then hides the HUD. - * - * @see showAnimated:whileExecutingBlock:onQueue:completionBlock: + * The HUD delegate object. Receives HUD state notifications. */ -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block; +@property (weak, nonatomic) id delegate; -/** - * Shows the HUD while a block is executing on a background queue, then hides the HUD. - * - * @see showAnimated:whileExecutingBlock:onQueue:completionBlock: +/* + * Grace period is the time (in seconds) that the invoked method may be run without + * showing the HUD. If the task finishes before the grace time runs out, the HUD will + * not be shown at all. + * This may be used to prevent HUD display for very short tasks. + * Defaults to 0 (no grace time). */ -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(MBProgressHUDCompletionBlock)completion; +@property (assign, nonatomic) NSTimeInterval graceTime; /** - * Shows the HUD while a block is executing on the specified dispatch queue, then hides the HUD. - * - * @see showAnimated:whileExecutingBlock:onQueue:completionBlock: - */ -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue; - -/** - * Shows the HUD while a block is executing on the specified dispatch queue, executes completion block on the main queue, and then hides the HUD. - * - * @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will - * not use animations while (dis)appearing. - * @param block The block to be executed while the HUD is shown. - * @param queue The dispatch queue on which the block should be executed. - * @param completion The block to be executed on completion. - * - * @see completionBlock + * The minimum time (in seconds) that the HUD is shown. + * This avoids the problem of the HUD being shown and than instantly hidden. + * Defaults to 0 (no minimum show time). */ -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue - completionBlock:(MBProgressHUDCompletionBlock)completion; +@property (assign, nonatomic) NSTimeInterval minShowTime; /** - * A block that gets called after the HUD was completely hidden. + * Removes the HUD from its parent view when hidden. + * Defaults to NO. */ -@property (copy) MBProgressHUDCompletionBlock completionBlock; +@property (assign, nonatomic) BOOL removeFromSuperViewOnHide; -#endif +/// @name Appearance /** * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. - * - * @see MBProgressHUDMode */ -@property (assign) MBProgressHUDMode mode; +@property (assign, nonatomic) MBProgressHUDMode mode; /** - * The animation type that should be used when the HUD is shown and hidden. - * - * @see MBProgressHUDAnimation + * A color that gets forwarded to all labels and supported indicators. Also sets the tintColor + * for custom views on iOS 7+. Set to nil to manage color individually. + * Defaults to semi-translucent black on iOS 7 and later and white on earlier iOS versions. */ -@property (assign) MBProgressHUDAnimation animationType; +@property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; /** - * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. - * For best results use a 37 by 37 pixel view (so the bounds match the built in indicator bounds). - */ -@property (MB_STRONG) UIView *customView; - -/** - * The HUD delegate object. - * - * @see MBProgressHUDDelegate - */ -@property (MB_WEAK) id delegate; - -/** - * An optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit - * the entire text. If the text is too long it will get clipped by displaying "..." at the end. If left unchanged or - * set to @"", then no message is displayed. - */ -@property (copy) NSString *labelText; - -/** - * An optional details message displayed below the labelText message. This message is displayed only if the labelText - * property is also set and is different from an empty string (@""). The details text can span multiple lines. - */ -@property (copy) NSString *detailsLabelText; - -/** - * The opacity of the HUD window. Defaults to 0.8 (80% opacity). + * The animation type that should be used when the HUD is shown and hidden. */ -@property (assign) CGFloat opacity; +@property (assign, nonatomic) MBProgressHUDAnimation animationType UI_APPEARANCE_SELECTOR; /** - * The color of the HUD window. Defaults to black. If this property is set, color is set using - * this UIColor and the opacity property is not used. using retain because performing copy on - * UIColor base colors (like [UIColor greenColor]) cause problems with the copyZone. + * The bezel offset relative to the center of the view. You can use MBProgressMaxOffset + * and -MBProgressMaxOffset to move the HUD all the way to the screen edge in each direction. + * E.g., CGPointMake(0.f, MBProgressMaxOffset) would position the HUD centered on the bottom edge. */ -@property (MB_STRONG) UIColor *color; - -/** - * The x-axis offset of the HUD relative to the centre of the superview. - */ -@property (assign) CGFloat xOffset; - -/** - * The y-axis offset of the HUD relative to the centre of the superview. - */ -@property (assign) CGFloat yOffset; +@property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; /** - * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). - * Defaults to 20.0 + * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). + * This also represents the minimum bezel distance to the edge of the HUD view. + * Defaults to 20.f */ -@property (assign) CGFloat margin; +@property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; /** - * The corner radius for the HUD - * Defaults to 10.0 - */ -@property (assign) float cornerRadius; - -/** - * Cover the HUD background view with a radial gradient. - */ -@property (assign) BOOL dimBackground; - -/* - * Grace period is the time (in seconds) that the invoked method may be run without - * showing the HUD. If the task finishes before the grace time runs out, the HUD will - * not be shown at all. - * This may be used to prevent HUD display for very short tasks. - * Defaults to 0 (no grace time). - * Grace time functionality is only supported when the task status is known! - * @see taskInProgress + * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). */ -@property (assign) CGFloat graceTime; +@property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; /** - * The minimum time (in seconds) that the HUD is shown. - * This avoids the problem of the HUD being shown and than instantly hidden. - * Defaults to 0 (no minimum show time). + * Force the HUD dimensions to be equal if possible. */ -@property (assign) CGFloat minShowTime; +@property (assign, nonatomic, getter = isSquare) BOOL square UI_APPEARANCE_SELECTOR; /** - * Indicates that the executed operation is in progress. Needed for correct graceTime operation. - * If you don't set a graceTime (different than 0.0) this does nothing. - * This property is automatically set when using showWhileExecuting:onTarget:withObject:animated:. - * When threading is done outside of the HUD (i.e., when the show: and hide: methods are used directly), - * you need to set this property when your task starts and completes in order to have normal graceTime - * functionality. + * When enabled, the bezel center gets slightly affected by the device accelerometer data. + * Has no effect on iOS < 7.0. Defaults to YES. */ -@property (assign) BOOL taskInProgress; +@property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled UI_APPEARANCE_SELECTOR; + +/// @name Progress /** - * Removes the HUD from its parent view when hidden. - * Defaults to NO. + * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. */ -@property (assign) BOOL removeFromSuperViewOnHide; +@property (assign, nonatomic) float progress; -/** - * Font to be used for the main label. Set this property if the default is not adequate. - */ -@property (MB_STRONG) UIFont* labelFont; +/// @name Views /** - * Color to be used for the main label. Set this property if the default is not adequate. + * The view containing the labels and indicator (or customView). */ -@property (MB_STRONG) UIColor* labelColor; +@property (strong, nonatomic, readonly) MBBackgroundView *bezelView; /** - * Font to be used for the details label. Set this property if the default is not adequate. + * View coving the entire HUD area, placed behind bezelView. */ -@property (MB_STRONG) UIFont* detailsLabelFont; - -/** - * Color to be used for the details label. Set this property if the default is not adequate. - */ -@property (MB_STRONG) UIColor* detailsLabelColor; +@property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; /** - * The color of the activity indicator. Defaults to [UIColor whiteColor] - * Does nothing on pre iOS 5. - */ -@property (MB_STRONG) UIColor *activityIndicatorColor; - -/** - * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. + * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. + * The view should implement intrinsicContentSize for proper sizing. For best results use approximately 37 by 37 pixel. */ -@property (assign) CGFloat progress; +@property (strong, nonatomic, nullable) UIView *customView; /** - * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). + * A label that holds an optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit + * the entire text. */ -@property (assign) CGSize minSize; - -- (void)hideAfterDelay:(NSTimeInterval)interval; - - +@property (strong, nonatomic, readonly) UILabel *label; /** - * The actual size of the HUD bezel. - * You can use this to limit touch handling on the bezel aria only. - * @see https://github.com/jdg/MBProgressHUD/pull/200 + * A label that holds an optional details message displayed below the labelText message. The details text can span multiple lines. */ -@property (atomic, assign, readonly) CGSize size; - +@property (strong, nonatomic, readonly) UILabel *detailsLabel; /** - * Force the HUD dimensions to be equal if possible. + * A button that is placed below the labels. Visible only if a target / action is added. */ -@property (assign, getter = isSquare) BOOL square; +@property (strong, nonatomic, readonly) UIButton *button; @end @@ -471,54 +311,114 @@ typedef void (^MBProgressHUDCompletionBlock)(); /** * Progress (0.0 to 1.0) */ -@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, assign) float progress; /** * Indicator progress color. * Defaults to white [UIColor whiteColor] */ -@property (nonatomic, MB_STRONG) UIColor *progressTintColor; +@property (nonatomic, strong) UIColor *progressTintColor; /** - * Indicator background (non-progress) color. + * Indicator background (non-progress) color. + * Only applicable on iOS version older than iOS 7. * Defaults to translucent white (alpha 0.1) */ -@property (nonatomic, MB_STRONG) UIColor *backgroundTintColor; +@property (nonatomic, strong) UIColor *backgroundTintColor; /* - * Display mode - NO = round or YES = annular. Defaults to round. + * Display mode - NO = round or YES = annular. De+faults to round. */ @property (nonatomic, assign, getter = isAnnular) BOOL annular; @end + /** * A flat bar progress view. */ @interface MBBarProgressView : UIView - /** * Progress (0.0 to 1.0) */ -@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, assign) float progress; /** * Bar border line color. * Defaults to white [UIColor whiteColor]. */ -@property (nonatomic, MB_STRONG) UIColor *lineColor; +@property (nonatomic, strong) UIColor *lineColor; /** * Bar background color. * Defaults to clear [UIColor clearColor]; */ -@property (nonatomic, MB_STRONG) UIColor *progressRemainingColor; +@property (nonatomic, strong) UIColor *progressRemainingColor; /** * Bar progress color. * Defaults to white [UIColor whiteColor]. */ -@property (nonatomic, MB_STRONG) UIColor *progressColor; +@property (nonatomic, strong) UIColor *progressColor; + +@end + + +@interface MBBackgroundView : UIView + +/** + * The background style. + * Defaults to MBProgressHUDBackgroundStyleBlur on iOS 7 or later and MBProgressHUDBackgroundStyleSolidColor otherwise. + * @note Due to iOS 7 not supporting UIVisualEffectView the blur effect differs slightly between iOS 7 and later versions. + */ +@property (nonatomic) MBProgressHUDBackgroundStyle style; + +/** + * The background color or the blur tint color. + * @note Due to iOS 7 not supporting UIVisualEffectView the blur effect differs slightly between iOS 7 and later versions. + */ +@property (nonatomic, strong) UIColor *color; @end + +@interface MBProgressHUD (Deprecated) + ++ (NSArray *)allHUDsForView:(UIView *)view __attribute__((deprecated("Store references when using more than one HUD per view."))); ++ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated __attribute__((deprecated("Store references when using more than one HUD per view."))); + +- (id)initWithWindow:(UIWindow *)window __attribute__((deprecated("Use initWithView: instead."))); + +- (void)show:(BOOL)animated __attribute__((deprecated("Use showAnimated: instead."))); +- (void)hide:(BOOL)animated __attribute__((deprecated("Use hideAnimated: instead."))); +- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay __attribute__((deprecated("Use hideAnimated:afterDelay: instead."))); + +typedef void (^MBProgressHUDCompletionBlock)(); + +- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated __attribute__((deprecated("Use GCD directly."))); +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block __attribute__((deprecated("Use GCD directly."))); +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(nullable MBProgressHUDCompletionBlock)completion __attribute__((deprecated("Use GCD directly."))); +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue __attribute__((deprecated("Use GCD directly."))); +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue + completionBlock:(nullable MBProgressHUDCompletionBlock)completion __attribute__((deprecated("Use GCD directly."))); +@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock __attribute__((deprecated("Use GCD directly."))); +@property (assign) BOOL taskInProgress __attribute__((deprecated("No longer needed."))); + +@property (nonatomic, copy) NSString *labelText __attribute__((deprecated("Use label.text instead."))); +@property (nonatomic, strong) UIFont *labelFont __attribute__((deprecated("Use label.font instead."))); +@property (nonatomic, strong) UIColor *labelColor __attribute__((deprecated("Use label.textColor instead."))); +@property (nonatomic, copy) NSString *detailsLabelText __attribute__((deprecated("Use detailsLabel.text instead."))); +@property (nonatomic, strong) UIFont *detailsLabelFont __attribute__((deprecated("Use detailsLabel.font instead."))); +@property (nonatomic, strong) UIColor *detailsLabelColor __attribute__((deprecated("Use detailsLabel.textColor instead."))); +@property (assign, nonatomic) CGFloat opacity __attribute__((deprecated("Customize bezelView properties instead."))); +@property (strong, nonatomic) UIColor *color __attribute__((deprecated("Customize the bezelView color instead."))); +@property (assign, nonatomic) CGFloat xOffset __attribute__((deprecated("Set offset.x instead."))); +@property (assign, nonatomic) CGFloat yOffset __attribute__((deprecated("Set offset.y instead."))); +@property (assign, nonatomic) CGFloat cornerRadius __attribute__((deprecated("Set bezelView.layer.cornerRadius instead."))); +@property (assign, nonatomic) BOOL dimBackground __attribute__((deprecated("Customize HUD background properties instead."))); +@property (strong, nonatomic) UIColor *activityIndicatorColor __attribute__((deprecated("Use UIAppearance to customize UIActivityIndicatorView."))); +@property (atomic, assign, readonly) CGSize size __attribute__((deprecated("Get the bezelView.frame.size instead."))); + +@end + +NS_ASSUME_NONNULL_END diff --git a/MBProgressHUD.m b/MBProgressHUD.m index e7bfe5690..c70edfc24 100644 --- a/MBProgressHUD.m +++ b/MBProgressHUD.m @@ -1,6 +1,6 @@ // // MBProgressHUD.m -// Version 0.9.1 +// Version 0.9.2 // Created by Matej Bukovinski on 2.4.09. // @@ -8,303 +8,187 @@ #import -#if __has_feature(objc_arc) - #define MB_AUTORELEASE(exp) exp - #define MB_RELEASE(exp) exp - #define MB_RETAIN(exp) exp -#else - #define MB_AUTORELEASE(exp) [exp autorelease] - #define MB_RELEASE(exp) [exp release] - #define MB_RETAIN(exp) [exp retain] -#endif - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 - #define MBLabelAlignmentCenter NSTextAlignmentCenter -#else - #define MBLabelAlignmentCenter UITextAlignmentCenter -#endif - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - #define MB_TEXTSIZE(text, font) [text length] > 0 ? [text \ - sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero; -#else - #define MB_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero; -#endif - -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 - #define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \ - boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin) \ - attributes:@{NSFontAttributeName:font} context:nil].size : CGSizeZero; -#else - #define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \ - sizeWithFont:font constrainedToSize:maxSize lineBreakMode:mode] : CGSizeZero; -#endif - #ifndef kCFCoreFoundationVersionNumber_iOS_7_0 - #define kCFCoreFoundationVersionNumber_iOS_7_0 847.20 + #define kCFCoreFoundationVersionNumber_iOS_7_0 847.20 #endif #ifndef kCFCoreFoundationVersionNumber_iOS_8_0 - #define kCFCoreFoundationVersionNumber_iOS_8_0 1129.15 + #define kCFCoreFoundationVersionNumber_iOS_8_0 1129.15 #endif +#define MBMainThreadAssert() NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); -static const CGFloat kPadding = 4.f; -static const CGFloat kLabelFontSize = 16.f; -static const CGFloat kDetailsLabelFontSize = 12.f; +CGFloat const MBProgressMaxOffset = 1000000.f; + +static const CGFloat MBDefaultPadding = 4.f; +static const CGFloat MBDefaultLabelFontSize = 16.f; +static const CGFloat MBDefaultDetailsLabelFontSize = 12.f; @interface MBProgressHUD () { - BOOL useAnimation; - SEL methodForExecution; - id targetForExecution; - id objectForExecution; - UILabel *label; - UILabel *detailsLabel; - BOOL isFinished; - CGAffineTransform rotationTransform; + // Depricated + UIColor *_activityIndicatorColor; + CGFloat _opacity; } -@property (atomic, MB_STRONG) UIView *indicator; -@property (atomic, MB_STRONG) NSTimer *graceTimer; -@property (atomic, MB_STRONG) NSTimer *minShowTimer; -@property (atomic, MB_STRONG) NSDate *showStarted; +@property (nonatomic, assign) BOOL useAnimation; +@property (nonatomic, assign, getter=hasFinished) BOOL finished; +@property (nonatomic, strong) UIView *indicator; +@property (nonatomic, strong) NSTimer *graceTimer; +@property (nonatomic, strong) NSTimer *minShowTimer; +@property (nonatomic, strong) NSDate *showStarted; +@property (nonatomic, strong) NSArray *paddingConstraints; +@property (nonatomic, strong) UIView *topSpacer; +@property (nonatomic, strong) UIView *bottomSpacer; + +// Deprecated +@property (copy, nullable) MBProgressHUDCompletionBlock completionBlock; +@property (assign) BOOL taskInProgress; @end -@implementation MBProgressHUD +@interface MBProgressHUDRoundedButton : UIButton +@end -#pragma mark - Properties -@synthesize animationType; -@synthesize delegate; -@synthesize opacity; -@synthesize color; -@synthesize labelFont; -@synthesize labelColor; -@synthesize detailsLabelFont; -@synthesize detailsLabelColor; -@synthesize indicator; -@synthesize xOffset; -@synthesize yOffset; -@synthesize minSize; -@synthesize square; -@synthesize margin; -@synthesize dimBackground; -@synthesize graceTime; -@synthesize minShowTime; -@synthesize graceTimer; -@synthesize minShowTimer; -@synthesize taskInProgress; -@synthesize removeFromSuperViewOnHide; -@synthesize customView; -@synthesize showStarted; -@synthesize mode; -@synthesize labelText; -@synthesize detailsLabelText; -@synthesize progress; -@synthesize size; -@synthesize activityIndicatorColor; -#if NS_BLOCKS_AVAILABLE -@synthesize completionBlock; -#endif +@implementation MBProgressHUD #pragma mark - Class methods -+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { - MBProgressHUD *hud = [[self alloc] initWithView:view]; - hud.removeFromSuperViewOnHide = YES; - [view addSubview:hud]; - [hud show:animated]; - return MB_AUTORELEASE(hud); ++ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { + MBProgressHUD *hud = [[self alloc] initWithView:view]; + hud.removeFromSuperViewOnHide = YES; + [view addSubview:hud]; + [hud showAnimated:animated]; + return hud; } + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated { - MBProgressHUD *hud = [self HUDForView:view]; - if (hud != nil) { - hud.removeFromSuperViewOnHide = YES; - [hud hide:animated]; - return YES; - } - return NO; + MBProgressHUD *hud = [self HUDForView:view]; + if (hud != nil) { + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:animated]; + return YES; + } + return NO; } -+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated { - NSArray *huds = [MBProgressHUD allHUDsForView:view]; - for (MBProgressHUD *hud in huds) { - hud.removeFromSuperViewOnHide = YES; - [hud hide:animated]; - } - return [huds count]; ++ (MBProgressHUD *)HUDForView:(UIView *)view { + NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; + for (UIView *subview in subviewsEnum) { + if ([subview isKindOfClass:self]) { + return (MBProgressHUD *)subview; + } + } + return nil; } -+ (MB_INSTANCETYPE)HUDForView:(UIView *)view { - NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; - for (UIView *subview in subviewsEnum) { - if ([subview isKindOfClass:self]) { - return (MBProgressHUD *)subview; - } - } - return nil; -} +#pragma mark - Lifecycle -+ (NSArray *)allHUDsForView:(UIView *)view { - NSMutableArray *huds = [NSMutableArray array]; - NSArray *subviews = view.subviews; - for (UIView *aView in subviews) { - if ([aView isKindOfClass:self]) { - [huds addObject:aView]; - } - } - return [NSArray arrayWithArray:huds]; +- (void)commonInit { + // Set default values for properties + _animationType = MBProgressHUDAnimationFade; + _mode = MBProgressHUDModeIndeterminate; + _margin = 20.0f; + _opacity = 1.f; + _defaultMotionEffectsEnabled = YES; + + // Default color, depending on the current iOS version + BOOL isLegacy = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; + _contentColor = isLegacy ? [UIColor whiteColor] : [UIColor colorWithWhite:0.f alpha:0.7f]; + // Transparent background + self.opaque = NO; + self.backgroundColor = [UIColor clearColor]; + // Make it invisible for now + self.alpha = 0.0f; + self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.layer.allowsGroupOpacity = NO; + + [self setupViews]; + [self updateIndicators]; + [self registerForNotifications]; } -#pragma mark - Lifecycle - -- (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - // Set default values for properties - self.animationType = MBProgressHUDAnimationFade; - self.mode = MBProgressHUDModeIndeterminate; - self.labelText = nil; - self.detailsLabelText = nil; - self.opacity = 0.8f; - self.color = nil; - self.labelFont = [UIFont boldSystemFontOfSize:kLabelFontSize]; - self.labelColor = [UIColor whiteColor]; - self.detailsLabelFont = [UIFont boldSystemFontOfSize:kDetailsLabelFontSize]; - self.detailsLabelColor = [UIColor whiteColor]; - self.activityIndicatorColor = [UIColor whiteColor]; - self.xOffset = 0.0f; - self.yOffset = 0.0f; - self.dimBackground = NO; - self.margin = 20.0f; - self.cornerRadius = 10.0f; - self.graceTime = 0.0f; - self.minShowTime = 0.0f; - self.removeFromSuperViewOnHide = NO; - self.minSize = CGSizeZero; - self.square = NO; - self.contentMode = UIViewContentModeCenter; - self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin - | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; - - // Transparent background - self.opaque = NO; - self.backgroundColor = [UIColor clearColor]; - // Make it invisible for now - self.alpha = 0.0f; - - taskInProgress = NO; - rotationTransform = CGAffineTransformIdentity; - - [self setupLabels]; - [self updateIndicators]; - [self registerForKVO]; - [self registerForNotifications]; - } - return self; +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + [self commonInit]; + } + return self; } -- (id)initWithView:(UIView *)view { - NSAssert(view, @"View must not be nil."); - return [self initWithFrame:view.bounds]; +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if ((self = [super initWithCoder:aDecoder])) { + [self commonInit]; + } + return self; } -- (id)initWithWindow:(UIWindow *)window { - return [self initWithView:window]; +- (id)initWithView:(UIView *)view { + NSAssert(view, @"View must not be nil."); + return [self initWithFrame:view.bounds]; } - (void)dealloc { - [self unregisterFromNotifications]; - [self unregisterFromKVO]; -#if !__has_feature(objc_arc) - [color release]; - [indicator release]; - [label release]; - [detailsLabel release]; - [labelText release]; - [detailsLabelText release]; - [graceTimer release]; - [minShowTimer release]; - [showStarted release]; - [customView release]; - [labelFont release]; - [labelColor release]; - [detailsLabelFont release]; - [detailsLabelColor release]; -#if NS_BLOCKS_AVAILABLE - [completionBlock release]; -#endif - [super dealloc]; -#endif + [self unregisterFromNotifications]; } #pragma mark - Show & hide -- (void)show:(BOOL)animated { - NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); - useAnimation = animated; - // If the grace time is set postpone the HUD display - if (self.graceTime > 0.0) { - NSTimer *newGraceTimer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:newGraceTimer forMode:NSRunLoopCommonModes]; - self.graceTimer = newGraceTimer; - } - // ... otherwise show the HUD imediately - else { - [self showUsingAnimation:useAnimation]; - } -} - -- (void)hideAnimated -{ - [self hide:YES]; -} - -- (void)hideAfterDelay:(NSTimeInterval)interval -{ - [self performSelector:@selector(hideAnimated) withObject:nil afterDelay:interval]; +- (void)showAnimated:(BOOL)animated { + MBMainThreadAssert(); + self.useAnimation = animated; + self.finished = NO; + // If the grace time is set postpone the HUD display + if (self.graceTime > 0.0) { + NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.graceTimer = timer; + } + // ... otherwise show the HUD imediately + else { + [self showUsingAnimation:self.useAnimation]; + } } -- (void)hide:(BOOL)animated { - NSAssert([NSThread isMainThread], @"MBProgressHUD needs to be accessed on the main thread."); - useAnimation = animated; - // If the minShow time is set, calculate how long the hud was shown, - // and pospone the hiding operation if necessary - if (self.minShowTime > 0.0 && showStarted) { - NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:showStarted]; - if (interv < self.minShowTime) { - self.minShowTimer = [NSTimer scheduledTimerWithTimeInterval:(self.minShowTime - interv) target:self - selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; - return; - } - } - // ... otherwise hide the HUD immediately - [self hideUsingAnimation:useAnimation]; +- (void)hideAnimated:(BOOL)animated { + MBMainThreadAssert(); + self.useAnimation = animated; + self.finished = YES; + // If the minShow time is set, calculate how long the hud was shown, + // and pospone the hiding operation if necessary + if (self.minShowTime > 0.0 && self.showStarted) { + NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted]; + if (interv < self.minShowTime) { + NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + self.minShowTimer = timer; + return; + } + } + // ... otherwise hide the HUD immediately + [self hideUsingAnimation:self.useAnimation]; } -- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay { - [self performSelector:@selector(hideDelayed:) withObject:[NSNumber numberWithBool:animated] afterDelay:delay]; +- (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay { + [self performSelector:@selector(hideDelayed:) withObject:[NSNumber numberWithBool:animated] afterDelay:delay]; } - (void)hideDelayed:(NSNumber *)animated { - [self hide:[animated boolValue]]; + [self hideAnimated:[animated boolValue]]; } #pragma mark - Timer callbacks - (void)handleGraceTimer:(NSTimer *)theTimer { - // Show the HUD only if the task is still running - if (taskInProgress) { - [self showUsingAnimation:useAnimation]; - } + // Show the HUD only if the task is still running + if (!self.hasFinished) { + [self showUsingAnimation:self.useAnimation]; + } } - (void)handleMinShowTimer:(NSTimer *)theTimer { - [self hideUsingAnimation:useAnimation]; + [self hideUsingAnimation:self.useAnimation]; } #pragma mark - View Hierrarchy @@ -318,471 +202,514 @@ - (void)didMoveToSuperview { - (void)showUsingAnimation:(BOOL)animated { // Cancel any scheduled hideDelayed: calls [NSObject cancelPreviousPerformRequestsWithTarget:self]; - [self setNeedsDisplay]; - - if (animated && animationType == MBProgressHUDAnimationZoomIn) { - self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f)); - } else if (animated && animationType == MBProgressHUDAnimationZoomOut) { - self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f)); - } - self.showStarted = [NSDate date]; - // Fade in - if (animated) { - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:0.30]; - self.alpha = 1.0f; - if (animationType == MBProgressHUDAnimationZoomIn || animationType == MBProgressHUDAnimationZoomOut) { - self.transform = rotationTransform; - } - [UIView commitAnimations]; - } - else { - self.alpha = 1.0f; - } + + self.showStarted = [NSDate date]; + self.alpha = 1.f; + + if (animated) { + [self animateIn:YES withType:self.animationType completion:NULL]; + } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + self.bezelView.alpha = self.opacity; +#pragma clang diagnostic pop + self.backgroundView.alpha = 1.f; + } } - (void)hideUsingAnimation:(BOOL)animated { - // Fade out - if (animated && showStarted) { - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:0.30]; - [UIView setAnimationDelegate:self]; - [UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)]; - // 0.02 prevents the hud from passing through touches during the animation the hud will get completely hidden - // in the done method - if (animationType == MBProgressHUDAnimationZoomIn) { - self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f)); - } else if (animationType == MBProgressHUDAnimationZoomOut) { - self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f)); - } - - self.alpha = 0.02f; - [UIView commitAnimations]; - } - else { - self.alpha = 0.0f; - [self done]; - } - self.showStarted = nil; -} - -- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void*)context { - [self done]; + if (animated && self.showStarted) { + [self animateIn:NO withType:self.animationType completion:^(BOOL finished) { + [self done]; + }]; + } else { + self.bezelView.alpha = 0.f; + self.backgroundView.alpha = 1.f; + [self done]; + } + self.showStarted = nil; } -- (void)done { - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - isFinished = YES; - self.alpha = 0.0f; - if (removeFromSuperViewOnHide) { - [self removeFromSuperview]; - } -#if NS_BLOCKS_AVAILABLE - if (self.completionBlock) { - self.completionBlock(); - self.completionBlock = NULL; - } +- (void)animateIn:(BOOL)animatingIn withType:(MBProgressHUDAnimation)type completion:(void(^)(BOOL finished))completion { + // Automatically determine the correct + if (type == MBProgressHUDAnimationZoom) { + type = animatingIn ? MBProgressHUDAnimationZoomIn : MBProgressHUDAnimationZoomOut; + } + + CGAffineTransform small = CGAffineTransformMakeScale(0.5f, 0.5f); + CGAffineTransform large = CGAffineTransformMakeScale(1.5f, 1.5f); + + // Set starting state + UIView *bezelView = self.bezelView; + if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomIn) { + bezelView.transform = small; + } else if (animatingIn && bezelView.alpha == 0.f && type == MBProgressHUDAnimationZoomOut) { + bezelView.transform = large; + } + + // Perform animations + dispatch_block_t animations = ^{ + if (animatingIn) { + bezelView.transform = CGAffineTransformIdentity; + } else if (!animatingIn && type == MBProgressHUDAnimationZoomIn) { + bezelView.transform = large; + } else if (!animatingIn && type == MBProgressHUDAnimationZoomOut) { + bezelView.transform = small; + } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + bezelView.alpha = animatingIn ? self.opacity : 0.f; +#pragma clang diagnostic pop + self.backgroundView.alpha = animatingIn ? 1.f : 0.f; + }; + + // Spring animations are nicer, but only available on iOS 7+ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) { + [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; + return; + } #endif - @strongify(self.delegate, strongDelegate); - if ([strongDelegate respondsToSelector:@selector(hudWasHidden:)]) { - [strongDelegate performSelector:@selector(hudWasHidden:) withObject:self]; - } + [UIView animateWithDuration:0.3 delay:0. options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion]; } -#pragma mark - Threading +- (void)done { + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + self.alpha = 0.0f; + if (self.removeFromSuperViewOnHide) { + [self removeFromSuperview]; + } + if (self.completionBlock) { + self.completionBlock(); + self.completionBlock = NULL; + } -- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated { - methodForExecution = method; - targetForExecution = MB_RETAIN(target); - objectForExecution = MB_RETAIN(object); - // Launch execution in new thread - self.taskInProgress = YES; - [NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil]; - // Show HUD view - [self show:animated]; + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(hudWasHidden:)]) { + [delegate performSelector:@selector(hudWasHidden:) withObject:self]; + } } -#if NS_BLOCKS_AVAILABLE +#pragma mark - UI -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; -} +- (void)setupViews { + UIColor *defaultColor = self.contentColor; + + MBBackgroundView *backgroundView = [[MBBackgroundView alloc] initWithFrame:self.bounds]; + backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + backgroundView.backgroundColor = [UIColor clearColor]; + backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + backgroundView.alpha = 0.f; + [self addSubview:backgroundView]; + _backgroundView = backgroundView; + + MBBackgroundView *bezelView = [MBBackgroundView new]; + bezelView.translatesAutoresizingMaskIntoConstraints = NO; + bezelView.layer.cornerRadius = 5.f; + bezelView.alpha = 0.f; + [self addSubview:bezelView]; + _bezelView = bezelView; + [self updateBezelMotionEffects]; + + UILabel *label = [UILabel new]; + label.adjustsFontSizeToFitWidth = NO; + label.textAlignment = NSTextAlignmentCenter; + label.textColor = defaultColor; + label.font = [UIFont boldSystemFontOfSize:MBDefaultLabelFontSize];; + _label = label; + + UILabel *detailsLabel = [UILabel new]; + detailsLabel.adjustsFontSizeToFitWidth = NO; + detailsLabel.textAlignment = NSTextAlignmentCenter; + detailsLabel.textColor = defaultColor; + detailsLabel.numberOfLines = 0; + detailsLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; + _detailsLabel = detailsLabel; + + UIButton *button = [MBProgressHUDRoundedButton buttonWithType:UIButtonTypeCustom]; + button.titleLabel.textAlignment = NSTextAlignmentCenter; + button.titleLabel.font = [UIFont boldSystemFontOfSize:MBDefaultDetailsLabelFontSize]; + [button setTitleColor:defaultColor forState:UIControlStateNormal]; + _button = button; + + for (UIView *view in @[label, detailsLabel, button]) { + view.translatesAutoresizingMaskIntoConstraints = NO; + [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; + [view setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; + [bezelView addSubview:view]; + } -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(void (^)())completion { - dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:completion]; + UIView *topSpacer = [UIView new]; + topSpacer.translatesAutoresizingMaskIntoConstraints = NO; + topSpacer.hidden = YES; + [bezelView addSubview:topSpacer]; + _topSpacer = topSpacer; + + UIView *bottomSpacer = [UIView new]; + bottomSpacer.translatesAutoresizingMaskIntoConstraints = NO; + bottomSpacer.hidden = YES; + [bezelView addSubview:bottomSpacer]; + _bottomSpacer = bottomSpacer; } -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue { - [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; -} +- (void)updateIndicators { + UIView *indicator = self.indicator; + BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; + BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]]; + + MBProgressHUDMode mode = self.mode; + if (mode == MBProgressHUDModeIndeterminate) { + if (!isActivityIndicator) { + // Update to indeterminate indicator + [indicator removeFromSuperview]; + indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + [(UIActivityIndicatorView *)indicator startAnimating]; + [self.bezelView addSubview:indicator]; + } + } + else if (mode == MBProgressHUDModeDeterminateHorizontalBar) { + // Update to bar determinate indicator + [indicator removeFromSuperview]; + indicator = [[MBBarProgressView alloc] init]; + [self.bezelView addSubview:indicator]; + } + else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) { + if (!isRoundIndicator) { + // Update to determinante indicator + [indicator removeFromSuperview]; + indicator = [[MBRoundProgressView alloc] init]; + [self.bezelView addSubview:indicator]; + } + if (mode == MBProgressHUDModeAnnularDeterminate) { + [(MBRoundProgressView *)indicator setAnnular:YES]; + } + } + else if (mode == MBProgressHUDModeCustomView && self.customView != indicator) { + // Update custom view indicator + [indicator removeFromSuperview]; + indicator = self.customView; + [self.bezelView addSubview:indicator]; + } + else if (mode == MBProgressHUDModeText) { + [indicator removeFromSuperview]; + indicator = nil; + } + indicator.translatesAutoresizingMaskIntoConstraints = NO; + self.indicator = indicator; + + if ([indicator respondsToSelector:@selector(setProgress:)]) { + [(id)indicator setValue:@(self.progress) forKey:@"progress"]; + } -- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue - completionBlock:(MBProgressHUDCompletionBlock)completion { - self.taskInProgress = YES; - self.completionBlock = completion; - dispatch_async(queue, ^(void) { - block(); - dispatch_async(dispatch_get_main_queue(), ^(void) { - [self cleanUp]; - }); - }); - [self show:animated]; + [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisHorizontal]; + [indicator setContentCompressionResistancePriority:998.f forAxis:UILayoutConstraintAxisVertical]; + + [self updateViewsForColor:self.contentColor]; + [self setNeedsUpdateConstraints]; } -#endif +- (void)updateViewsForColor:(UIColor *)color { + if (!color) return; + + self.label.textColor = color; + self.detailsLabel.textColor = color; + [self.button setTitleColor:color forState:UIControlStateNormal]; -- (void)launchExecution { - @autoreleasepool { #pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - // Start executing the requested task - [targetForExecution performSelector:methodForExecution withObject:objectForExecution]; +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if (self.activityIndicatorColor) { + color = self.activityIndicatorColor; + } #pragma clang diagnostic pop - // Task completed, update view in main thread (note: view operations should - // be done only in the main thread) - [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO]; - } + + UIView *indicator = self.indicator; + if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { + ((UIActivityIndicatorView *)indicator).color = color; + } else if ([indicator isKindOfClass:[MBRoundProgressView class]]) { + ((MBRoundProgressView *)indicator).progressTintColor = color; + ((MBRoundProgressView *)indicator).backgroundTintColor = [color colorWithAlphaComponent:0.1]; + } else if ([indicator isKindOfClass:[MBBarProgressView class]]) { + ((MBBarProgressView *)indicator).progressColor = color; + ((MBBarProgressView *)indicator).lineColor = color; + } else { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + if ([indicator respondsToSelector:@selector(setTintColor:)]) { + [indicator setTintColor:color]; + } +#endif + } } -- (void)cleanUp { - taskInProgress = NO; -#if !__has_feature(objc_arc) - [targetForExecution release]; - [objectForExecution release]; -#else - targetForExecution = nil; - objectForExecution = nil; +- (void)updateBezelMotionEffects { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 + MBBackgroundView *bezelView = self.bezelView; + if (![bezelView respondsToSelector:@selector(addMotionEffect:)]) return; + + if (self.defaultMotionEffectsEnabled) { + CGFloat effectOffset = 10.f; + UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; + effectX.maximumRelativeValue = @(effectOffset); + effectX.minimumRelativeValue = @(-effectOffset); + + UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; + effectY.maximumRelativeValue = @(effectOffset); + effectY.minimumRelativeValue = @(-effectOffset); + + UIMotionEffectGroup *group = [[UIMotionEffectGroup alloc] init]; + group.motionEffects = @[effectX, effectY]; + + [bezelView addMotionEffect:group]; + } else { + NSArray *effects = [bezelView motionEffects]; + for (UIMotionEffect *effect in effects) { + [bezelView removeMotionEffect:effect]; + } + } #endif - [self hide:useAnimation]; } -#pragma mark - UI +#pragma mark - Layout -- (void)setupLabels { - label = [[UILabel alloc] initWithFrame:self.bounds]; - label.adjustsFontSizeToFitWidth = NO; - label.textAlignment = MBLabelAlignmentCenter; - label.opaque = NO; - label.backgroundColor = [UIColor clearColor]; - label.textColor = self.labelColor; - label.font = self.labelFont; - label.text = self.labelText; - [self addSubview:label]; - - detailsLabel = [[UILabel alloc] initWithFrame:self.bounds]; - detailsLabel.font = self.detailsLabelFont; - detailsLabel.adjustsFontSizeToFitWidth = NO; - detailsLabel.textAlignment = MBLabelAlignmentCenter; - detailsLabel.opaque = NO; - detailsLabel.backgroundColor = [UIColor clearColor]; - detailsLabel.textColor = self.detailsLabelColor; - detailsLabel.numberOfLines = 0; - detailsLabel.font = self.detailsLabelFont; - detailsLabel.text = self.detailsLabelText; - [self addSubview:detailsLabel]; +- (void)updateConstraints { + [super updateConstraints]; + + UIView *bezel = self.bezelView; + CGFloat margin = self.margin; + NSDictionary *metrics = @{@"margin": @(margin)}; + + NSMutableArray *subviews = [NSMutableArray arrayWithObjects:self.topSpacer, self.label, self.detailsLabel, self.button, self.bottomSpacer, nil]; + if (self.indicator) [subviews insertObject:self.indicator atIndex:1]; + + // Remove existing constraintes + [self removeConstraints:self.constraints]; + [bezel removeConstraints:bezel.constraints]; + + // Bump content hugging, to get the smallest bezel posible + [bezel setContentHuggingPriority:UILayoutPriorityDefaultLow + 1 forAxis:UILayoutConstraintAxisHorizontal]; + [bezel setContentHuggingPriority:UILayoutPriorityDefaultLow + 1 forAxis:UILayoutConstraintAxisVertical]; + + // Center bezel in container (self), applying the offset if set + CGPoint offset = self.offset; + NSMutableArray *centeringConstraints = [NSMutableArray array]; + [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.f constant:offset.x]]; + [centeringConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.f constant:offset.y]]; + [self applyPriority:998.f toConstraints:centeringConstraints]; + [self addConstraints:centeringConstraints]; + + // Ensure minimum side margin is kept + NSMutableArray *sideConstraints = [NSMutableArray array]; + [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; + [sideConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=margin)-[bezel]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(bezel)]]; + [self applyPriority:999.f toConstraints:sideConstraints]; + [self addConstraints:sideConstraints]; + + // Minimum bezel size, if set + CGSize minimumSize = self.minSize; + if (!CGSizeEqualToSize(minimumSize, CGSizeZero)) { + NSMutableArray *minSizeConstraints = [NSMutableArray array]; + [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.width]]; + [minSizeConstraints addObject:[NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:minimumSize.height]]; + [self applyPriority:997.f toConstraints:minSizeConstraints]; + [bezel addConstraints:minSizeConstraints]; + } + + // Square aspect ratio, if set + if (self.square) { + NSLayoutConstraint *square = [NSLayoutConstraint constraintWithItem:bezel attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeWidth multiplier:1.f constant:0]; + square.priority = 997.f; + [bezel addConstraint:square]; + } + + // Top and bottom spacing + UIView *topSpacer = self.topSpacer; + [topSpacer addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; + UIView *bottomSpacer = self.bottomSpacer; + [bottomSpacer addConstraint:[NSLayoutConstraint constraintWithItem:bottomSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:margin]]; + // Top and bottom spaces should be equal + [bezel addConstraint:[NSLayoutConstraint constraintWithItem:topSpacer attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:bottomSpacer attribute:NSLayoutAttributeHeight multiplier:1.f constant:0.f]]; + + // Layout subviews in bezel + NSMutableArray *paddingConstraints = [NSMutableArray new]; + [subviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { + // Center in bezel + [bezel addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeCenterX multiplier:1.f constant:0.f]]; + // Ensure the minimum edge margin is kept + [bezel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>=margin)-[view]-(>=margin)-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(view)]]; + // Element spacing + if (idx == 0) { + // First, ensure spacing to bezel edge + [bezel addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeTop multiplier:1.f constant:0.f]]; + } else if (idx == subviews.count - 1) { + // Last, ensure spacigin to bezel edge + [bezel addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bezel attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]]; + } + if (idx > 0) { + // Has previous + NSLayoutConstraint *padding = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:subviews[idx - 1] attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f]; + [bezel addConstraint:padding]; + [paddingConstraints addObject:padding]; + } + }]; + + self.paddingConstraints = [paddingConstraints copy]; + [self updatePaddingConstraints]; } -- (void)updateIndicators { - - BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; - BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]]; - - if (mode == MBProgressHUDModeIndeterminate) { - if (!isActivityIndicator) { - // Update to indeterminate indicator - [indicator removeFromSuperview]; - self.indicator = MB_AUTORELEASE([[UIActivityIndicatorView alloc] - initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]); - [(UIActivityIndicatorView *)indicator startAnimating]; - [self addSubview:indicator]; - } -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000 - [(UIActivityIndicatorView *)indicator setColor:self.activityIndicatorColor]; -#endif - } - else if (mode == MBProgressHUDModeDeterminateHorizontalBar) { - // Update to bar determinate indicator - [indicator removeFromSuperview]; - self.indicator = MB_AUTORELEASE([[MBBarProgressView alloc] init]); - [self addSubview:indicator]; - } - else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) { - if (!isRoundIndicator) { - // Update to determinante indicator - [indicator removeFromSuperview]; - self.indicator = MB_AUTORELEASE([[MBRoundProgressView alloc] init]); - [self addSubview:indicator]; - } - if (mode == MBProgressHUDModeAnnularDeterminate) { - [(MBRoundProgressView *)indicator setAnnular:YES]; - } - } - else if (mode == MBProgressHUDModeCustomView && customView != indicator) { - // Update custom view indicator - [indicator removeFromSuperview]; - self.indicator = customView; - [self addSubview:indicator]; - } else if (mode == MBProgressHUDModeText) { - [indicator removeFromSuperview]; - self.indicator = nil; - } +- (void)layoutSubviews { + [self updatePaddingConstraints]; + [super layoutSubviews]; } -#pragma mark - Layout +- (void)updatePaddingConstraints { + // Set padding dynamically, depending on whether the view is visible or not + __block BOOL hasVisibleAncestors = NO; + [self.paddingConstraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *padding, NSUInteger idx, BOOL *stop) { + UIView *firstView = (UIView *)padding.firstItem; + UIView *secondView = (UIView *)padding.secondItem; + BOOL firstVisible = !firstView.hidden && !CGSizeEqualToSize(firstView.intrinsicContentSize, CGSizeZero); + BOOL secondVisible = !secondView.hidden && !CGSizeEqualToSize(secondView.intrinsicContentSize, CGSizeZero); + // Set if both views are visible of if there's a visible view on top that yet doesn't have padding + // added relative to the current view + padding.constant = (firstVisible && (secondVisible || hasVisibleAncestors)) ? MBDefaultPadding : 0.f; + hasVisibleAncestors |= secondVisible; + }]; +} -- (void)layoutSubviews { - [super layoutSubviews]; - - // Entirely cover the parent view - UIView *parent = self.superview; - if (parent) { - self.frame = parent.bounds; - } - CGRect bounds = self.bounds; - - // Determine the total widt and height needed - CGFloat maxWidth = bounds.size.width - 4 * margin; - CGSize totalSize = CGSizeZero; - - CGRect indicatorF = indicator.bounds; - indicatorF.size.width = MIN(indicatorF.size.width, maxWidth); - totalSize.width = MAX(totalSize.width, indicatorF.size.width); - totalSize.height += indicatorF.size.height; - - CGSize labelSize = MB_TEXTSIZE(label.text, label.font); - labelSize.width = MIN(labelSize.width, maxWidth); - totalSize.width = MAX(totalSize.width, labelSize.width); - totalSize.height += labelSize.height; - if (labelSize.height > 0.f && indicatorF.size.height > 0.f) { - totalSize.height += kPadding; - } - - CGFloat remainingHeight = bounds.size.height - totalSize.height - kPadding - 4 * margin; - CGSize maxSize = CGSizeMake(maxWidth, remainingHeight); - CGSize detailsLabelSize = MB_MULTILINE_TEXTSIZE(detailsLabel.text, detailsLabel.font, maxSize, detailsLabel.lineBreakMode); - totalSize.width = MAX(totalSize.width, detailsLabelSize.width); - totalSize.height += detailsLabelSize.height; - if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) { - totalSize.height += kPadding; - } - - totalSize.width += 2 * margin; - totalSize.height += 2 * margin; - - // Position elements - CGFloat yPos = round(((bounds.size.height - totalSize.height) / 2)) + margin + yOffset; - CGFloat xPos = xOffset; - indicatorF.origin.y = yPos; - indicatorF.origin.x = round((bounds.size.width - indicatorF.size.width) / 2) + xPos; - indicator.frame = indicatorF; - yPos += indicatorF.size.height; - - if (labelSize.height > 0.f && indicatorF.size.height > 0.f) { - yPos += kPadding; - } - CGRect labelF; - labelF.origin.y = yPos; - labelF.origin.x = round((bounds.size.width - labelSize.width) / 2) + xPos; - labelF.size = labelSize; - label.frame = labelF; - yPos += labelF.size.height; - - if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) { - yPos += kPadding; - } - CGRect detailsLabelF; - detailsLabelF.origin.y = yPos; - detailsLabelF.origin.x = round((bounds.size.width - detailsLabelSize.width) / 2) + xPos; - detailsLabelF.size = detailsLabelSize; - detailsLabel.frame = detailsLabelF; - - // Enforce minsize and quare rules - if (square) { - CGFloat max = MAX(totalSize.width, totalSize.height); - if (max <= bounds.size.width - 2 * margin) { - totalSize.width = max; - } - if (max <= bounds.size.height - 2 * margin) { - totalSize.height = max; - } - } - if (totalSize.width < minSize.width) { - totalSize.width = minSize.width; - } - if (totalSize.height < minSize.height) { - totalSize.height = minSize.height; - } - - size = totalSize; -} - -#pragma mark BG Drawing +- (void)applyPriority:(UILayoutPriority)priority toConstraints:(NSArray *)constraints { + for (NSLayoutConstraint *constraint in constraints) { + constraint.priority = priority; + } +} -- (void)drawRect:(CGRect)rect { - - CGContextRef context = UIGraphicsGetCurrentContext(); - UIGraphicsPushContext(context); - - if (self.dimBackground) { - //Gradient colours - size_t gradLocationsNum = 2; - CGFloat gradLocations[2] = {0.0f, 1.0f}; - CGFloat gradColors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum); - CGColorSpaceRelease(colorSpace); - //Gradient center - CGPoint gradCenter= CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); - //Gradient radius - float gradRadius = MIN(self.bounds.size.width , self.bounds.size.height) ; - //Gradient draw - CGContextDrawRadialGradient (context, gradient, gradCenter, - 0, gradCenter, gradRadius, - kCGGradientDrawsAfterEndLocation); - CGGradientRelease(gradient); - } - - // Set background rect color - if (self.color) { - CGContextSetFillColorWithColor(context, self.color.CGColor); - } else { - CGContextSetGrayFillColor(context, 0.0f, self.opacity); - } - - - // Center HUD - CGRect allRect = self.bounds; - // Draw rounded HUD backgroud rect - CGRect boxRect = CGRectMake(round((allRect.size.width - size.width) / 2) + self.xOffset, - round((allRect.size.height - size.height) / 2) + self.yOffset, size.width, size.height); - float radius = self.cornerRadius; - CGContextBeginPath(context); - CGContextMoveToPoint(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect)); - CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMinY(boxRect) + radius, radius, 3 * (float)M_PI / 2, 0, 0); - CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMaxY(boxRect) - radius, radius, 0, (float)M_PI / 2, 0); - CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMaxY(boxRect) - radius, radius, (float)M_PI / 2, (float)M_PI, 0); - CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect) + radius, radius, (float)M_PI, 3 * (float)M_PI / 2, 0); - CGContextClosePath(context); - CGContextFillPath(context); - - UIGraphicsPopContext(); -} - -#pragma mark - KVO - -- (void)registerForKVO { - for (NSString *keyPath in [self observableKeypaths]) { - [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; - } -} - -- (void)unregisterFromKVO { - for (NSString *keyPath in [self observableKeypaths]) { - [self removeObserver:self forKeyPath:keyPath]; - } -} - -- (NSArray *)observableKeypaths { - return [NSArray arrayWithObjects:@"mode", @"customView", @"labelText", @"labelFont", @"labelColor", - @"detailsLabelText", @"detailsLabelFont", @"detailsLabelColor", @"progress", @"activityIndicatorColor", nil]; -} - -#define RADIANS(degrees) ((degrees * (CGFloat)M_PI) / 180.0f) - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if (![NSThread isMainThread]) { - [self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO]; - } else { - [self updateUIForKeypath:keyPath]; - } -} - -- (void)updateUIForKeypath:(NSString *)keyPath { - if ([keyPath isEqualToString:@"mode"] || [keyPath isEqualToString:@"customView"] || - [keyPath isEqualToString:@"activityIndicatorColor"]) { - [self updateIndicators]; - } else if ([keyPath isEqualToString:@"labelText"]) { - label.text = self.labelText; - } else if ([keyPath isEqualToString:@"labelFont"]) { - label.font = self.labelFont; - } else if ([keyPath isEqualToString:@"labelColor"]) { - label.textColor = self.labelColor; - } else if ([keyPath isEqualToString:@"detailsLabelText"]) { - detailsLabel.text = self.detailsLabelText; - } else if ([keyPath isEqualToString:@"detailsLabelFont"]) { - detailsLabel.font = self.detailsLabelFont; - } else if ([keyPath isEqualToString:@"detailsLabelColor"]) { - detailsLabel.textColor = self.detailsLabelColor; - } else if ([keyPath isEqualToString:@"progress"]) { - if ([indicator respondsToSelector:@selector(setProgress:)]) { - [(id)indicator setValue:@(progress) forKey:@"progress"]; - } - return; - } - [self setNeedsLayout]; - [self setNeedsDisplay]; +#pragma mark - Properties + +- (void)setMode:(MBProgressHUDMode)mode { + if (mode != _mode) { + _mode = mode; + [self updateIndicators]; + } +} + +- (void)setCustomView:(UIView *)customView { + if (customView != _customView) { + _customView = customView; + if (self.mode == MBProgressHUDModeCustomView) { + [self updateIndicators]; + } + } +} + +- (void)setOffset:(CGPoint)offset { + if (!CGPointEqualToPoint(offset, _offset)) { + _offset = offset; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setMargin:(CGFloat)margin { + if (margin != margin) { + _margin = margin; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setMinSize:(CGSize)minSize { + if (!CGSizeEqualToSize(minSize, _minSize)) { + _minSize = minSize; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setSquare:(BOOL)square { + if (square != _square) { + _square = square; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + UIView *indicator = self.indicator; + if ([indicator respondsToSelector:@selector(setProgress:)]) { + [(id)indicator setValue:@(self.progress) forKey:@"progress"]; + } + } +} + +- (void)setContentColor:(UIColor *)contentColor { + if (contentColor != _contentColor && ![contentColor isEqual:_contentColor]) { + _contentColor = contentColor; + [self updateViewsForColor:contentColor]; + } +} + +- (void)setDefaultMotionEffectsEnabled:(BOOL)defaultMotionEffectsEnabled { + if (defaultMotionEffectsEnabled != _defaultMotionEffectsEnabled) { + _defaultMotionEffectsEnabled = defaultMotionEffectsEnabled; + [self updateBezelMotionEffects]; + } } #pragma mark - Notifications - (void)registerForNotifications { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; +#if !TARGET_OS_TV + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self selector:@selector(statusBarOrientationDidChange:) - name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; + [nc addObserver:self selector:@selector(statusBarOrientationDidChange:) + name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif } - (void)unregisterFromNotifications { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#if !TARGET_OS_TV + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; +#endif } +#if !TARGET_OS_TV - (void)statusBarOrientationDidChange:(NSNotification *)notification { - UIView *superview = self.superview; - if (!superview) { - return; - } else { - [self updateForCurrentOrientationAnimated:YES]; - } + UIView *superview = self.superview; + if (!superview) { + return; + } else { + [self updateForCurrentOrientationAnimated:YES]; + } } +#endif - (void)updateForCurrentOrientationAnimated:(BOOL)animated { // Stay in sync with the superview in any case if (self.superview) { self.bounds = self.superview.bounds; - [self setNeedsDisplay]; } // Not needed on iOS 8+, compile out when the deployment target allows, // to avoid sharedApplication problems on extension targets #if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 - // Only needed pre iOS 7 when added to a window + // Only needed pre iOS 8 when added to a window BOOL iOS8OrLater = kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0; if (iOS8OrLater || ![self.superview isKindOfClass:[UIWindow class]]) return; - UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; - CGFloat radians = 0; - if (UIInterfaceOrientationIsLandscape(orientation)) { - if (orientation == UIInterfaceOrientationLandscapeLeft) { radians = -(CGFloat)M_PI_2; } - else { radians = (CGFloat)M_PI_2; } - // Window coordinates differ! - self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); - } else { - if (orientation == UIInterfaceOrientationPortraitUpsideDown) { radians = (CGFloat)M_PI; } - else { radians = 0; } - } - rotationTransform = CGAffineTransformMakeRotation(radians); - - if (animated) { - [UIView beginAnimations:nil context:nil]; - [UIView setAnimationDuration:0.3]; - } - [self setTransform:rotationTransform]; - if (animated) { - [UIView commitAnimations]; - } + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + CGFloat radians = 0; + if (UIInterfaceOrientationIsLandscape(orientation)) { + radians = orientation == UIInterfaceOrientationLandscapeLeft ? -(CGFloat)M_PI_2 : (CGFloat)M_PI_2; + // Window coordinates differ! + self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); + } else { + radians = orientation == UIInterfaceOrientationPortraitUpsideDown ? (CGFloat)M_PI : 0.f; + } + + if (animated) { + [UIView animateWithDuration:0.3 animations:^{ + self.transform = CGAffineTransformMakeRotation(radians); + }]; + } else { + self.transform = CGAffineTransformMakeRotation(radians); + } #endif } @@ -794,102 +721,117 @@ @implementation MBRoundProgressView #pragma mark - Lifecycle - (id)init { - return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; + return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; } - (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - self.backgroundColor = [UIColor clearColor]; - self.opaque = NO; - _progress = 0.f; - _annular = NO; - _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; - _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; - [self registerForKVO]; - } - return self; + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + _progress = 0.f; + _annular = NO; + _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; + _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; + } + return self; } -- (void)dealloc { - [self unregisterFromKVO]; -#if !__has_feature(objc_arc) - [_progressTintColor release]; - [_backgroundTintColor release]; - [super dealloc]; -#endif +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + return CGSizeMake(37.f, 37.f); +} + +#pragma mark - Properties + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + [self setNeedsDisplay]; + } +} + +- (void)setProgressTintColor:(UIColor *)progressTintColor { + NSAssert(progressTintColor, @"The color should not be nil."); + if (progressTintColor != _progressTintColor && ![progressTintColor isEqual:_progressTintColor]) { + _progressTintColor = progressTintColor; + [self setNeedsDisplay]; + } +} + +- (void)setBackgroundTintColor:(UIColor *)backgroundTintColor { + NSAssert(backgroundTintColor, @"The color should not be nil."); + if (backgroundTintColor != _backgroundTintColor && ![backgroundTintColor isEqual:_backgroundTintColor]) { + _backgroundTintColor = backgroundTintColor; + [self setNeedsDisplay]; + } } #pragma mark - Drawing - (void)drawRect:(CGRect)rect { - - CGRect allRect = self.bounds; - CGRect circleRect = CGRectInset(allRect, 2.0f, 2.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - - if (_annular) { - // Draw background - BOOL isPreiOS7 = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; - CGFloat lineWidth = isPreiOS7 ? 5.f : 2.f; - UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; - processBackgroundPath.lineWidth = lineWidth; - processBackgroundPath.lineCapStyle = kCGLineCapButt; - CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); - CGFloat radius = (self.bounds.size.width - lineWidth)/2; - CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees - CGFloat endAngle = (2 * (float)M_PI) + startAngle; - [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - [_backgroundTintColor set]; - [processBackgroundPath stroke]; - // Draw progress - UIBezierPath *processPath = [UIBezierPath bezierPath]; - processPath.lineCapStyle = isPreiOS7 ? kCGLineCapRound : kCGLineCapSquare; - processPath.lineWidth = lineWidth; - endAngle = (self.progress * 2 * (float)M_PI) + startAngle; - [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; - [_progressTintColor set]; - [processPath stroke]; - } else { - // Draw background - [_progressTintColor setStroke]; - [_backgroundTintColor setFill]; - CGContextSetLineWidth(context, 2.0f); - CGContextFillEllipseInRect(context, circleRect); - CGContextStrokeEllipseInRect(context, circleRect); - // Draw progress - CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2); - CGFloat radius = (allRect.size.width - 4) / 2; - CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees - CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle; - [_progressTintColor setFill]; - CGContextMoveToPoint(context, center.x, center.y); - CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0); - CGContextClosePath(context); - CGContextFillPath(context); - } -} - -#pragma mark - KVO - -- (void)registerForKVO { - for (NSString *keyPath in [self observableKeypaths]) { - [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; - } -} - -- (void)unregisterFromKVO { - for (NSString *keyPath in [self observableKeypaths]) { - [self removeObserver:self forKeyPath:keyPath]; - } -} - -- (NSArray *)observableKeypaths { - return [NSArray arrayWithObjects:@"progressTintColor", @"backgroundTintColor", @"progress", @"annular", nil]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - [self setNeedsDisplay]; + CGContextRef context = UIGraphicsGetCurrentContext(); + BOOL isPreiOS7 = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; + + if (_annular) { + // Draw background + CGFloat lineWidth = isPreiOS7 ? 5.f : 2.f; + UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; + processBackgroundPath.lineWidth = lineWidth; + processBackgroundPath.lineCapStyle = kCGLineCapButt; + CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + CGFloat radius = (self.bounds.size.width - lineWidth)/2; + CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees + CGFloat endAngle = (2 * (float)M_PI) + startAngle; + [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + [_backgroundTintColor set]; + [processBackgroundPath stroke]; + // Draw progress + UIBezierPath *processPath = [UIBezierPath bezierPath]; + processPath.lineCapStyle = isPreiOS7 ? kCGLineCapRound : kCGLineCapSquare; + processPath.lineWidth = lineWidth; + endAngle = (self.progress * 2 * (float)M_PI) + startAngle; + [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + [_progressTintColor set]; + [processPath stroke]; + } else { + // Draw background + CGFloat lineWidth = 2.f; + CGRect allRect = self.bounds; + CGRect circleRect = CGRectInset(allRect, lineWidth/2.f, lineWidth/2.f); + CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + [_progressTintColor setStroke]; + [_backgroundTintColor setFill]; + CGContextSetLineWidth(context, lineWidth); + if (isPreiOS7) { + CGContextFillEllipseInRect(context, circleRect); + } + CGContextStrokeEllipseInRect(context, circleRect); + // 90 degrees + CGFloat startAngle = - ((float)M_PI / 2.f); + // Draw progress + if (isPreiOS7) { + CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - lineWidth; + CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; + [_progressTintColor setFill]; + CGContextMoveToPoint(context, center.x, center.y); + CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0); + CGContextClosePath(context); + CGContextFillPath(context); + } else { + UIBezierPath *processPath = [UIBezierPath bezierPath]; + processPath.lineCapStyle = kCGLineCapButt; + processPath.lineWidth = lineWidth * 2.f; + CGFloat radius = (CGRectGetWidth(self.bounds) / 2.f) - (processPath.lineWidth / 2.f); + CGFloat endAngle = (self.progress * 2.f * (float)M_PI) + startAngle; + [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; + // Ensure that we don't get color overlaping when _progressTintColor alpha < 1.f. + CGContextSetBlendMode(context, kCGBlendModeCopy); + [_progressTintColor set]; + [processPath stroke]; + } + } } @end @@ -900,139 +842,520 @@ @implementation MBBarProgressView #pragma mark - Lifecycle - (id)init { - return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; + return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; } - (id)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _progress = 0.f; - _lineColor = [UIColor whiteColor]; - _progressColor = [UIColor whiteColor]; - _progressRemainingColor = [UIColor clearColor]; - self.backgroundColor = [UIColor clearColor]; - self.opaque = NO; - [self registerForKVO]; - } - return self; + self = [super initWithFrame:frame]; + if (self) { + _progress = 0.f; + _lineColor = [UIColor whiteColor]; + _progressColor = [UIColor whiteColor]; + _progressRemainingColor = [UIColor clearColor]; + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + } + return self; } -- (void)dealloc { - [self unregisterFromKVO]; -#if !__has_feature(objc_arc) - [_lineColor release]; - [_progressColor release]; - [_progressRemainingColor release]; - [super dealloc]; -#endif +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + BOOL isPreiOS7 = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; + return CGSizeMake(120.f, isPreiOS7 ? 20.f : 10.f); +} + +#pragma mark - Properties + +- (void)setProgress:(float)progress { + if (progress != _progress) { + _progress = progress; + [self setNeedsDisplay]; + } +} + +- (void)setProgressColor:(UIColor *)progressColor { + NSAssert(progressColor, @"The color should not be nil."); + if (progressColor != _progressColor && ![progressColor isEqual:_progressColor]) { + _progressColor = progressColor; + [self setNeedsDisplay]; + } +} + +- (void)setProgressRemainingColor:(UIColor *)progressRemainingColor { + NSAssert(progressRemainingColor, @"The color should not be nil."); + if (progressRemainingColor != _progressRemainingColor && ![progressRemainingColor isEqual:_progressRemainingColor]) { + _progressRemainingColor = progressRemainingColor; + [self setNeedsDisplay]; + } } #pragma mark - Drawing - (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGContextSetLineWidth(context, 2); - CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); - CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); - - // Draw background - float radius = (rect.size.height / 2) - 2; - CGContextMoveToPoint(context, 2, rect.size.height/2); - CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2); - CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); - CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); - CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2); - CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); - CGContextFillPath(context); - - // Draw border - CGContextMoveToPoint(context, 2, rect.size.height/2); - CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2); - CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); - CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); - CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2); - CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); - CGContextStrokePath(context); - - CGContextSetFillColorWithColor(context, [_progressColor CGColor]); - radius = radius - 2; - float amount = self.progress * rect.size.width; - - // Progress in the middle area - if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, amount, 4); - CGContextAddLineToPoint(context, amount, radius + 4); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, amount, rect.size.height - 4); - CGContextAddLineToPoint(context, amount, radius + 4); - - CGContextFillPath(context); - } - - // Progress in the right arc - else if (amount > radius + 4) { - float x = amount - (rect.size.width - radius - 4); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); - float angle = -acos(x/radius); - if (isnan(angle)) angle = 0; - CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); - CGContextAddLineToPoint(context, amount, rect.size.height/2); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); - angle = acos(x/radius); - if (isnan(angle)) angle = 0; - CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); - CGContextAddLineToPoint(context, amount, rect.size.height/2); - - CGContextFillPath(context); - } - - // Progress is in the left arc - else if (amount < radius + 4 && amount > 0) { - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); - CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); - - CGContextMoveToPoint(context, 4, rect.size.height/2); - CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); - CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); - - CGContextFillPath(context); - } -} - -#pragma mark - KVO - -- (void)registerForKVO { - for (NSString *keyPath in [self observableKeypaths]) { - [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; - } -} - -- (void)unregisterFromKVO { - for (NSString *keyPath in [self observableKeypaths]) { - [self removeObserver:self forKeyPath:keyPath]; - } -} - -- (NSArray *)observableKeypaths { - return [NSArray arrayWithObjects:@"lineColor", @"progressRemainingColor", @"progressColor", @"progress", nil]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - [self setNeedsDisplay]; + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetLineWidth(context, 2); + CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); + CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); + + // Draw background + CGFloat radius = (rect.size.height / 2) - 2; + CGContextMoveToPoint(context, 2, rect.size.height/2); + CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2); + CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); + CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); + CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2); + CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); + CGContextFillPath(context); + + // Draw border + CGContextMoveToPoint(context, 2, rect.size.height/2); + CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2); + CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); + CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); + CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2); + CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); + CGContextStrokePath(context); + + CGContextSetFillColorWithColor(context, [_progressColor CGColor]); + radius = radius - 2; + CGFloat amount = self.progress * rect.size.width; + + // Progress in the middle area + if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, amount, 4); + CGContextAddLineToPoint(context, amount, radius + 4); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, amount, rect.size.height - 4); + CGContextAddLineToPoint(context, amount, radius + 4); + + CGContextFillPath(context); + } + + // Progress in the right arc + else if (amount > radius + 4) { + CGFloat x = amount - (rect.size.width - radius - 4); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); + CGFloat angle = -acos(x/radius); + if (isnan(angle)) angle = 0; + CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); + CGContextAddLineToPoint(context, amount, rect.size.height/2); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); + angle = acos(x/radius); + if (isnan(angle)) angle = 0; + CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); + CGContextAddLineToPoint(context, amount, rect.size.height/2); + + CGContextFillPath(context); + } + + // Progress is in the left arc + else if (amount < radius + 4 && amount > 0) { + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); + CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); + + CGContextMoveToPoint(context, 4, rect.size.height/2); + CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); + CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); + + CGContextFillPath(context); + } +} + +@end + + +@interface MBBackgroundView () + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 +@property UIVisualEffectView *effectView; +#endif +@property UIToolbar *toolbar; + +@end + + +@implementation MBBackgroundView + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) { + _style = MBProgressHUDBackgroundStyleBlur; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + _color = [UIColor colorWithWhite:0.8f alpha:0.6f]; +#else + _color = [UIColor colorWithWhite:0.95f alpha:0.6f]; +#endif + } else { + _style = MBProgressHUDBackgroundStyleSolidColor; + _color = [[UIColor blackColor] colorWithAlphaComponent:0.8]; + } + + self.clipsToBounds = YES; + + [self updateForBackgroundStyle]; + } + return self; +} + +#pragma mark - Layout + +- (CGSize)intrinsicContentSize { + // Smallest size possible. Content pushes against this. + return CGSizeZero; +} + +#pragma mark - Appearance + +- (void)setStyle:(MBProgressHUDBackgroundStyle)style { + if (style == MBProgressHUDBackgroundStyleBlur && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0) { + style = MBProgressHUDBackgroundStyleSolidColor; + } + if (_style != style) { + _style = style; + [self updateForBackgroundStyle]; + } +} + +- (void)setColor:(UIColor *)color { + NSAssert(color, @"The color should not be nil."); + if (color != _color && ![color isEqual:_color]) { + _color = color; + [self updateViewsForColor:color]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - Views + +- (void)updateForBackgroundStyle { + MBProgressHUDBackgroundStyle style = self.style; + if (style == MBProgressHUDBackgroundStyleBlur) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; + [self addSubview:effectView]; + effectView.frame = self.bounds; + effectView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.backgroundColor = self.color; + self.layer.allowsGroupOpacity = NO; + self.effectView = effectView; +#else + UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectInset(self.bounds, -100.f, -100.f)]; + toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + toolbar.barTintColor = self.color; + toolbar.translucent = YES; + toolbar.barTintColor = color; + [self addSubview:toolbar]; + self.toolbar = toolbar; +#endif + } else { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + [self.effectView removeFromSuperview]; + self.effectView = nil; +#else + [self.toolbar removeFromSuperview]; + self.toolbar = nil; +#endif + self.backgroundColor = self.color; + } +} + +- (void)updateViewsForColor:(UIColor *)color { + if (self.style == MBProgressHUDBackgroundStyleBlur) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + self.backgroundColor = self.color; +#else + self.toolbar.barTintColor = color; +#endif + } else { + self.backgroundColor = self.color; + } +} + +@end + + +@implementation MBProgressHUD (Deprecated) + +#pragma mark - Class + ++ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated { + NSArray *huds = [MBProgressHUD allHUDsForView:view]; + for (MBProgressHUD *hud in huds) { + hud.removeFromSuperViewOnHide = YES; + [hud hideAnimated:animated]; + } + return [huds count]; +} + ++ (NSArray *)allHUDsForView:(UIView *)view { + NSMutableArray *huds = [NSMutableArray array]; + NSArray *subviews = view.subviews; + for (UIView *aView in subviews) { + if ([aView isKindOfClass:self]) { + [huds addObject:aView]; + } + } + return [NSArray arrayWithArray:huds]; +} + +#pragma mark - Lifecycle + +- (id)initWithWindow:(UIWindow *)window { + return [self initWithView:window]; +} + +#pragma mark - Show & hide + +- (void)show:(BOOL)animated { + [self showAnimated:animated]; +} + +- (void)hide:(BOOL)animated { + [self hideAnimated:animated]; +} + +- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay { + [self hideAnimated:animated afterDelay:delay]; +} + +#pragma mark - Threading + +- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated { + [self showAnimated:animated whileExecutingBlock:^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + // Start executing the requested task + [target performSelector:method withObject:object]; +#pragma clang diagnostic pop + }]; +} + +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block { + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; +} + +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(void (^)())completion { + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:completion]; +} + +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue { + [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; +} + +- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue completionBlock:(nullable MBProgressHUDCompletionBlock)completion { + self.taskInProgress = YES; + self.completionBlock = completion; + dispatch_async(queue, ^(void) { + block(); + dispatch_async(dispatch_get_main_queue(), ^(void) { + [self cleanUp]; + }); + }); + [self showAnimated:animated]; +} + +- (void)cleanUp { + self.taskInProgress = NO; + [self hideAnimated:self.useAnimation]; +} + +#pragma mark - Labels + +- (NSString *)labelText { + return self.label.text; +} + +- (void)setLabelText:(NSString *)labelText { + MBMainThreadAssert(); + self.label.text = labelText; +} + +- (UIFont *)labelFont { + return self.label.font; +} + +- (void)setLabelFont:(UIFont *)labelFont { + MBMainThreadAssert(); + self.label.font = labelFont; +} + +- (UIColor *)labelColor { + return self.label.textColor; +} + +- (void)setLabelColor:(UIColor *)labelColor { + MBMainThreadAssert(); + self.label.textColor = labelColor; +} + +- (NSString *)detailsLabelText { + return self.detailsLabel.text; +} + +- (void)setDetailsLabelText:(NSString *)detailsLabelText { + MBMainThreadAssert(); + self.detailsLabel.text = detailsLabelText; +} + +- (UIFont *)detailsLabelFont { + return self.detailsLabel.font; +} + +- (void)setDetailsLabelFont:(UIFont *)detailsLabelFont { + MBMainThreadAssert(); + self.detailsLabel.font = detailsLabelFont; +} + +- (UIColor *)detailsLabelColor { + return self.detailsLabel.textColor; +} + +- (void)setDetailsLabelColor:(UIColor *)detailsLabelColor { + MBMainThreadAssert(); + self.detailsLabel.textColor = detailsLabelColor; +} + +- (CGFloat)opacity { + return _opacity; +} + +- (void)setOpacity:(CGFloat)opacity { + MBMainThreadAssert(); + _opacity = opacity; +} + +- (UIColor *)color { + return self.bezelView.color; +} + +- (void)setColor:(UIColor *)color { + MBMainThreadAssert(); + self.bezelView.color = color; +} + +- (CGFloat)yOffset { + return self.offset.y; +} + +- (void)setYOffset:(CGFloat)yOffset { + MBMainThreadAssert(); + self.offset = CGPointMake(self.offset.x, yOffset); +} + +- (CGFloat)xOffset { + return self.offset.x; +} + +- (void)setXOffset:(CGFloat)xOffset { + MBMainThreadAssert(); + self.offset = CGPointMake(xOffset, self.offset.y); +} + +- (CGFloat)cornerRadius { + return self.bezelView.layer.cornerRadius; +} + +- (void)setCornerRadius:(CGFloat)cornerRadius { + MBMainThreadAssert(); + self.bezelView.layer.cornerRadius = cornerRadius; +} + +- (BOOL)dimBackground { + MBBackgroundView *backgroundView = self.backgroundView; + UIColor *dimmedColor = [UIColor colorWithWhite:0.f alpha:.2f]; + return backgroundView.style == MBProgressHUDBackgroundStyleSolidColor && [backgroundView.color isEqual:dimmedColor]; +} + +- (void)setDimBackground:(BOOL)dimBackground { + MBMainThreadAssert(); + self.backgroundView.style = MBProgressHUDBackgroundStyleSolidColor; + self.backgroundView.color = dimBackground ? [UIColor colorWithWhite:0.f alpha:.2f] : [UIColor clearColor]; +} + +- (CGSize)size { + return self.bezelView.frame.size; +} + +- (UIColor *)activityIndicatorColor { + return _activityIndicatorColor; +} + +- (void)setActivityIndicatorColor:(UIColor *)activityIndicatorColor { + if (activityIndicatorColor != _activityIndicatorColor) { + _activityIndicatorColor = activityIndicatorColor; + UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)self.indicator; + if ([indicator isKindOfClass:[UIActivityIndicatorView class]]) { + [indicator setColor:activityIndicatorColor]; + } + } +} + +@end + +@implementation MBProgressHUDRoundedButton + +#pragma mark - Lifecycle + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + CALayer *layer = self.layer; + layer.borderWidth = 1.f; + } + return self; +} + +#pragma mark - Layout + +- (void)layoutSubviews { + [super layoutSubviews]; + // Fully rounded corners. + CGFloat height = CGRectGetHeight(self.bounds); + self.layer.cornerRadius = ceil(height / 2.f); +} + +- (CGSize)intrinsicContentSize { + // Only show, if we have associated control events. + if (self.allControlEvents == 0) return CGSizeZero; + CGSize size = [super intrinsicContentSize]; + // Add some side padding. + size.width += 20.f; + return size; +} + +#pragma mark - Color + +- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state { + [super setTitleColor:color forState:state]; + // Update related colors. + [self setHighlighted:self.highlighted]; + self.layer.borderColor = color.CGColor; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + UIColor *baseColor = [self titleColorForState:UIControlStateSelected]; + self.backgroundColor = highlighted ? [baseColor colorWithAlphaComponent:0.1f] : [UIColor clearColor]; } @end diff --git a/MBProgressHUD.podspec b/MBProgressHUD.podspec index 40f188826..afbd61087 100644 --- a/MBProgressHUD.podspec +++ b/MBProgressHUD.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "MBProgressHUD" - s.version = "0.9.1" + s.version = "0.9.2" s.summary = "An iOS activity indicator view." s.description = <<-DESC MBProgressHUD is an iOS drop-in class that displays a translucent HUD diff --git a/MBProgressHUD.xcodeproj/project.pbxproj b/MBProgressHUD.xcodeproj/project.pbxproj index c2a0f8df5..20e9a54dc 100644 --- a/MBProgressHUD.xcodeproj/project.pbxproj +++ b/MBProgressHUD.xcodeproj/project.pbxproj @@ -8,6 +8,8 @@ /* Begin PBXBuildFile section */ 1315DD7617804CBC0032507D /* MBProgressHUD.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D286A7511518C70F00E13FB8 /* MBProgressHUD.h */; }; + 1D104D931ACA371400973364 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = D286A7521518C70F00E13FB8 /* MBProgressHUD.m */; }; + 1D104D941ACA373100973364 /* MBProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = D286A7511518C70F00E13FB8 /* MBProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; D286A74D1518C70F00E13FB8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D286A74C1518C70F00E13FB8 /* Foundation.framework */; }; D286A7531518C70F00E13FB8 /* MBProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = D286A7521518C70F00E13FB8 /* MBProgressHUD.m */; }; D286A75E1518C89600E13FB8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D286A75D1518C89600E13FB8 /* UIKit.framework */; }; @@ -29,6 +31,8 @@ /* Begin PBXFileReference section */ 1315DD73178045000032507D /* MBProgressHUD-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MBProgressHUD-Prefix.pch"; sourceTree = SOURCE_ROOT; }; + 1D104D7A1ACA36CC00973364 /* MBProgressHUD.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MBProgressHUD.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1D104D951ACA376200973364 /* Framework-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Framework-Info.plist"; sourceTree = SOURCE_ROOT; }; D286A7491518C70F00E13FB8 /* libMBProgressHUD.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMBProgressHUD.a; sourceTree = BUILT_PRODUCTS_DIR; }; D286A74C1518C70F00E13FB8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D286A7511518C70F00E13FB8 /* MBProgressHUD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBProgressHUD.h; sourceTree = SOURCE_ROOT; }; @@ -38,6 +42,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 1D104D761ACA36CC00973364 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D286A7461518C70F00E13FB8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -54,6 +65,7 @@ 1315DD72178044770032507D /* Supporting Files */ = { isa = PBXGroup; children = ( + 1D104D951ACA376200973364 /* Framework-Info.plist */, 1315DD73178045000032507D /* MBProgressHUD-Prefix.pch */, ); name = "Supporting Files"; @@ -72,6 +84,7 @@ isa = PBXGroup; children = ( D286A7491518C70F00E13FB8 /* libMBProgressHUD.a */, + 1D104D7A1ACA36CC00973364 /* MBProgressHUD.framework */, ); name = Products; sourceTree = ""; @@ -98,10 +111,39 @@ }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + 1D104D771ACA36CC00973364 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D104D941ACA373100973364 /* MBProgressHUD.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ - D286A7481518C70F00E13FB8 /* MBProgressHUD */ = { + 1D104D791ACA36CC00973364 /* MBProgressHUD Framework */ = { isa = PBXNativeTarget; - buildConfigurationList = D286A7561518C70F00E13FB8 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */; + buildConfigurationList = 1D104D8D1ACA36CC00973364 /* Build configuration list for PBXNativeTarget "MBProgressHUD Framework" */; + buildPhases = ( + 1D104D751ACA36CC00973364 /* Sources */, + 1D104D761ACA36CC00973364 /* Frameworks */, + 1D104D771ACA36CC00973364 /* Headers */, + 1D104D781ACA36CC00973364 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "MBProgressHUD Framework"; + productName = "MBProgressHUD Framework"; + productReference = 1D104D7A1ACA36CC00973364 /* MBProgressHUD.framework */; + productType = "com.apple.product-type.framework"; + }; + D286A7481518C70F00E13FB8 /* MBProgressHUD Static Library */ = { + isa = PBXNativeTarget; + buildConfigurationList = D286A7561518C70F00E13FB8 /* Build configuration list for PBXNativeTarget "MBProgressHUD Static Library" */; buildPhases = ( D286A7451518C70F00E13FB8 /* Sources */, D286A7461518C70F00E13FB8 /* Frameworks */, @@ -111,7 +153,7 @@ ); dependencies = ( ); - name = MBProgressHUD; + name = "MBProgressHUD Static Library"; productName = MBProgressHUD; productReference = D286A7491518C70F00E13FB8 /* libMBProgressHUD.a */; productType = "com.apple.product-type.library.static"; @@ -123,8 +165,16 @@ isa = PBXProject; attributes = { CLASSPREFIX = MB; - LastUpgradeCheck = 0460; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Matej Bukovinski"; + TargetAttributes = { + 1D104D791ACA36CC00973364 = { + CreatedOnToolsVersion = 6.2; + }; + D286A7481518C70F00E13FB8 = { + LastSwiftMigration = 0810; + }; + }; }; buildConfigurationList = D286A7431518C70E00E13FB8 /* Build configuration list for PBXProject "MBProgressHUD" */; compatibilityVersion = "Xcode 3.2"; @@ -138,12 +188,31 @@ projectDirPath = ""; projectRoot = ""; targets = ( - D286A7481518C70F00E13FB8 /* MBProgressHUD */, + D286A7481518C70F00E13FB8 /* MBProgressHUD Static Library */, + 1D104D791ACA36CC00973364 /* MBProgressHUD Framework */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + 1D104D781ACA36CC00973364 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ + 1D104D751ACA36CC00973364 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D104D931ACA371400973364 /* MBProgressHUD.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D286A7451518C70F00E13FB8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -155,21 +224,175 @@ /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ + 1D104D8E1ACA36CC00973364 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "Framework-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.matej.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MBProgressHUD; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1D104D8F1ACA36CC00973364 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "Framework-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.matej.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MBProgressHUD; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C38D09661C65837A00D639D7 /* QADeployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; + SDKROOT = iphoneos; + }; + name = QADeployment; + }; + C38D09671C65837A00D639D7 /* QADeployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/MBProgressHUD.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MBProgressHUD-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = MBProgressHUD; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + }; + name = QADeployment; + }; + C38D09681C65837A00D639D7 /* QADeployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "Framework-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.matej.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = MBProgressHUD; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = QADeployment; + }; D286A7541518C70F00E13FB8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -183,7 +406,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; @@ -195,14 +418,22 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Distribution"; COPY_PHASE_STRIP = YES; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -210,7 +441,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 4.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.2; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; @@ -223,8 +454,9 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "MBProgressHUD-Prefix.pch"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = MBProgressHUD; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,27 +467,40 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "MBProgressHUD-Prefix.pch"; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = MBProgressHUD; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 1D104D8D1ACA36CC00973364 /* Build configuration list for PBXNativeTarget "MBProgressHUD Framework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D104D8E1ACA36CC00973364 /* Debug */, + C38D09681C65837A00D639D7 /* QADeployment */, + 1D104D8F1ACA36CC00973364 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D286A7431518C70E00E13FB8 /* Build configuration list for PBXProject "MBProgressHUD" */ = { isa = XCConfigurationList; buildConfigurations = ( D286A7541518C70F00E13FB8 /* Debug */, + C38D09661C65837A00D639D7 /* QADeployment */, D286A7551518C70F00E13FB8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D286A7561518C70F00E13FB8 /* Build configuration list for PBXNativeTarget "MBProgressHUD" */ = { + D286A7561518C70F00E13FB8 /* Build configuration list for PBXNativeTarget "MBProgressHUD Static Library" */ = { isa = XCConfigurationList; buildConfigurations = ( D286A7571518C70F00E13FB8 /* Debug */, + C38D09671C65837A00D639D7 /* QADeployment */, D286A7581518C70F00E13FB8 /* Release */, ); defaultConfigurationIsVisible = 0; diff --git a/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD Framework.xcscheme b/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD Framework.xcscheme new file mode 100644 index 000000000..189d4531b --- /dev/null +++ b/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD Framework.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD.xcscheme b/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD.xcscheme index 6033e19d9..fcc8708f4 100644 --- a/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD.xcscheme +++ b/MBProgressHUD.xcodeproj/xcshareddata/xcschemes/MBProgressHUD.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> + + @@ -52,10 +55,10 @@ 0.9.1'` +1. Add a pod entry for MBProgressHUD to your Podfile `pod 'MBProgressHUD', '~> 0.9.2'` 2. Install the pod(s) by running `pod install`. 3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. +### Carthage + +1. Add MBProgressHUD to your Cartfile. e.g., `github "jdg/MBProgressHUD" ~> 0.9.2` +2. Run `carthage update` +3. Follow the rest of the [standard Carthage installation instructions](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add MBProgressHUD to your project. + ### Source files Alternatively you can directly add the `MBProgressHUD.h` and `MBProgressHUD.m` source files to your project. -1. Download the [latest code version](https://github.com/matej/MBProgressHUD/archive/master.zip) or add the repository as a git submodule to your git-tracked project. -2. Open your project in Xcode, then drag and drop `MBProgressHUD.h` and `MBProgressHUD.m` onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project. +1. Download the [latest code version](https://github.com/matej/MBProgressHUD/archive/master.zip) or add the repository as a git submodule to your git-tracked project. +2. Open your project in Xcode, then drag and drop `MBProgressHUD.h` and `MBProgressHUD.m` onto your project (use the "Product Navigator view"). Make sure to select Copy items when asked if you extracted the code archive outside of your project. 3. Include MBProgressHUD wherever you need it with `#import "MBProgressHUD.h"`. ### Static library -You can also add MBProgressHUD as a static library to your project or workspace. +You can also add MBProgressHUD as a static library to your project or workspace. -1. Download the [latest code version](https://github.com/matej/MBProgressHUD/downloads) or add the repository as a git submodule to your git-tracked project. -2. Open your project in Xcode, then drag and drop `MBProgressHUD.xcodeproj` onto your project or workspace (use the "Product Navigator view"). -3. Select your target and go to the Build phases tab. In the Link Binary With Libraries section select the add button. On the sheet find and add `libMBProgressHUD.a`. You might also need to add `MBProgressHUD` to the Target Dependencies list. +1. Download the [latest code version](https://github.com/matej/MBProgressHUD/downloads) or add the repository as a git submodule to your git-tracked project. +2. Open your project in Xcode, then drag and drop `MBProgressHUD.xcodeproj` onto your project or workspace (use the "Product Navigator view"). +3. Select your target and go to the Build phases tab. In the Link Binary With Libraries section select the add button. On the sheet find and add `libMBProgressHUD.a`. You might also need to add `MBProgressHUD` to the Target Dependencies list. 4. Include MBProgressHUD wherever you need it with `#import `. ## Usage -The main guideline you need to follow when dealing with MBProgressHUD while running long-running tasks is keeping the main thread work-free, so the UI can be updated promptly. The recommended way of using MBProgressHUD is therefore to set it up on the main thread and then spinning the task, that you want to perform, off onto a new thread. +The main guideline you need to follow when dealing with MBProgressHUD while running long-running tasks is keeping the main thread work-free, so the UI can be updated promptly. The recommended way of using MBProgressHUD is therefore to set it up on the main thread and then spinning the task, that you want to perform, off onto a new thread. ```objective-c [MBProgressHUD showHUDAddedTo:self.view animated:YES]; @@ -61,7 +72,7 @@ dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ }); ``` -If you need to configure the HUD you can do this by using the MBProgressHUD reference that showHUDAddedTo:animated: returns. +If you need to configure the HUD you can do this by using the MBProgressHUD reference that showHUDAddedTo:animated: returns. ```objective-c MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; @@ -94,8 +105,8 @@ For more examples, including how to use MBProgressHUD with asynchronous operatio ## License -This code is distributed under the terms and conditions of the [MIT license](LICENSE). +This code is distributed under the terms and conditions of the [MIT license](LICENSE). ## Change-log -A brief summary of each MBProgressHUD release can be found on the [wiki](https://github.com/matej/MBProgressHUD/wiki/Change-log). +A brief summary of each MBProgressHUD release can be found in the [CHANGELOG](CHANGELOG.mdown).