diff options
author | Paul Beusterien <paulbeusterien@google.com> | 2017-05-15 12:27:07 -0700 |
---|---|---|
committer | Paul Beusterien <paulbeusterien@google.com> | 2017-05-15 12:27:07 -0700 |
commit | 98ba64449a632518bd2b86fe8d927f4a960d3ddc (patch) | |
tree | 131d9c4272fa6179fcda6c5a33fcb3b1bd57ad2e /AuthSamples/Sample/UIViewController+Alerts.m | |
parent | 32461366c9e204a527ca05e6e9b9404a2454ac51 (diff) |
Initial
Diffstat (limited to 'AuthSamples/Sample/UIViewController+Alerts.m')
-rw-r--r-- | AuthSamples/Sample/UIViewController+Alerts.m | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/AuthSamples/Sample/UIViewController+Alerts.m b/AuthSamples/Sample/UIViewController+Alerts.m new file mode 100644 index 0000000..76ef067 --- /dev/null +++ b/AuthSamples/Sample/UIViewController+Alerts.m @@ -0,0 +1,346 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "UIViewController+Alerts.h" + +#import <objc/runtime.h> + +/*! @var kPleaseWaitAssociatedObjectKey + @brief Key used to identify the "please wait" spinner associated object. + */ +static NSString *const kPleaseWaitAssociatedObjectKey = + @"_UIViewControllerAlertCategory_PleaseWaitScreenAssociatedObject"; + +/*! @var kUseStatusBarSpinnerAssociatedObjectKey + @brief The address of this constant is the key used to identify the "use status bar spinner" + associated object. + */ +static const void *const kUseStatusBarSpinnerAssociatedObjectKey; + +/*! @var kOK + @brief Text for an 'OK' button. + */ +static NSString *const kOK = @"OK"; + +/*! @var kCancel + @brief Text for an 'Cancel' button. + */ +static NSString *const kCancel = @"Cancel"; + +/*! @class SimpleTextPromptDelegate + @brief A @c UIAlertViewDelegate which allows @c UIAlertView to be used with blocks more easily. + */ +@interface SimpleTextPromptDelegate : NSObject <UIAlertViewDelegate> + +/*! @fn init + @brief Please use initWithCompletionHandler. + */ +- (nullable instancetype)init NS_UNAVAILABLE; + +/*! @fn initWithCompletionHandler: + @brief Designated initializer. + @param completionHandler The block to call when the alert view is dismissed. + */ +- (nullable instancetype)initWithCompletionHandler:(AlertPromptCompletionBlock)completionHandler + NS_DESIGNATED_INITIALIZER; + +@end + +@implementation UIViewController (Alerts) + +- (void)setUseStatusBarSpinner:(BOOL)useStatusBarSpinner { + objc_setAssociatedObject(self, + &kUseStatusBarSpinnerAssociatedObjectKey, + useStatusBarSpinner ? @(YES) : nil, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (BOOL)useStatusBarSpinner { + return objc_getAssociatedObject(self, &kUseStatusBarSpinnerAssociatedObjectKey) ? YES : NO; +} + +/*! @fn supportsAlertController + @brief Determines if the current platform supports @c UIAlertController. + @return YES if the current platform supports @c UIAlertController. + */ +- (BOOL)supportsAlertController { + return NSClassFromString(@"UIAlertController") != nil; +} + +- (void)showMessagePrompt:(NSString *)message { + [self showMessagePromptWithTitle:nil message:message showCancelButton:NO completion:nil]; +} + +- (void)showMessagePromptWithTitle:(nullable NSString *)title + message:(NSString *)message + showCancelButton:(BOOL)showCancelButton + completion:(nullable AlertPromptCompletionBlock)completion { + if (message) { + [UIPasteboard generalPasteboard].string = message; + } + if ([self supportsAlertController]) { + UIAlertController *alert = + [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *okAction = + [UIAlertAction actionWithTitle:kOK + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + if (completion) { + completion(YES, nil); + } + }]; + [alert addAction:okAction]; + + if (showCancelButton) { + UIAlertAction *cancelAction = + [UIAlertAction actionWithTitle:kCancel + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * _Nonnull action) { + completion(NO, nil); + }]; + [alert addAction:cancelAction]; + } + [self presentViewController:alert animated:YES completion:nil]; + } else { + UIAlertView *alert = + [[UIAlertView alloc] initWithTitle:title + message:message + delegate:nil + cancelButtonTitle:nil + otherButtonTitles:kOK, nil]; + [alert show]; + } +} + +- (void)showTextInputPromptWithMessage:(NSString *)message + completionBlock:(AlertPromptCompletionBlock)completion { + [self showTextInputPromptWithMessage:message + keyboardType:UIKeyboardTypeDefault + completionBlock:completion]; +} + +- (void)showTextInputPromptWithMessage:(NSString *)message + keyboardType:(UIKeyboardType)keyboardType + completionBlock:(nonnull AlertPromptCompletionBlock)completion { + if ([self supportsAlertController]) { + UIAlertController *prompt = + [UIAlertController alertControllerWithTitle:nil + message:message + preferredStyle:UIAlertControllerStyleAlert]; + __weak UIAlertController *weakPrompt = prompt; + UIAlertAction *cancelAction = + [UIAlertAction actionWithTitle:kCancel + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * _Nonnull action) { + completion(NO, nil); + }]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:kOK + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + UIAlertController *strongPrompt = weakPrompt; + completion(YES, strongPrompt.textFields[0].text); + }]; + [prompt addTextFieldWithConfigurationHandler:^(UITextField *_Nonnull textField) { + textField.keyboardType = keyboardType; + }]; + [prompt addAction:cancelAction]; + [prompt addAction:okAction]; + [self presentViewController:prompt animated:YES completion:nil]; + } else { + SimpleTextPromptDelegate *prompt = + [[SimpleTextPromptDelegate alloc] initWithCompletionHandler:completion]; + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil + message:message + delegate:prompt + cancelButtonTitle:@"Cancel" + otherButtonTitles:@"Ok", nil]; + alertView.alertViewStyle = UIAlertViewStylePlainTextInput; + [alertView show]; + } +} + +- (void)showSpinner:(nullable void(^)(void))completion { + if (self.useStatusBarSpinner) { + [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; + completion(); + return; + } + if ([self supportsAlertController]) { + [self showModernSpinner:completion]; + } else { + [self showIOS7Spinner:completion]; + } +} + +- (void)showModernSpinner:(nullable void (^)(void))completion { + UIAlertController *pleaseWaitAlert = + objc_getAssociatedObject(self, + (__bridge const void *)kPleaseWaitAssociatedObjectKey); + if (pleaseWaitAlert) { + if (completion) { + completion(); + } + return; + } + pleaseWaitAlert = [UIAlertController alertControllerWithTitle:nil + message:@"Please Wait...\n\n\n\n" + preferredStyle:UIAlertControllerStyleAlert]; + + UIActivityIndicatorView *spinner = + [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + spinner.color = [UIColor blackColor]; + spinner.center = CGPointMake(pleaseWaitAlert.view.bounds.size.width / 2, + pleaseWaitAlert.view.bounds.size.height / 2); + spinner.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | + UIViewAutoresizingFlexibleTopMargin | + UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleRightMargin; + [spinner startAnimating]; + [pleaseWaitAlert.view addSubview:spinner]; + + objc_setAssociatedObject(self, + (__bridge const void *)(kPleaseWaitAssociatedObjectKey), + pleaseWaitAlert, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + [self presentViewController:pleaseWaitAlert animated:YES completion:completion]; +} + +- (void)showIOS7Spinner:(nullable void (^)(void))completion { + UIWindow *pleaseWaitWindow = + objc_getAssociatedObject(self, + (__bridge const void *)kPleaseWaitAssociatedObjectKey); + + if (pleaseWaitWindow) { + if (completion) { + completion(); + } + return; + } + + pleaseWaitWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + pleaseWaitWindow.backgroundColor = [UIColor clearColor]; + pleaseWaitWindow.windowLevel = UIWindowLevelStatusBar - 1; + + UIView *pleaseWaitView = [[UIView alloc] initWithFrame:pleaseWaitWindow.bounds]; + pleaseWaitView.autoresizingMask = UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; + pleaseWaitView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5]; + UIActivityIndicatorView *spinner = + [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + spinner.center = pleaseWaitView.center; + [pleaseWaitView addSubview:spinner]; + [spinner startAnimating]; + + pleaseWaitView.layer.opacity = 0.0; + [self.view addSubview:pleaseWaitView]; + + [pleaseWaitWindow addSubview:pleaseWaitView]; + + [pleaseWaitWindow makeKeyAndVisible]; + + objc_setAssociatedObject(self, + (__bridge const void *)(kPleaseWaitAssociatedObjectKey), + pleaseWaitWindow, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + [UIView animateWithDuration:0.5f animations:^{ + pleaseWaitView.layer.opacity = 1.0f; + } completion:^(BOOL finished) { + if (completion) { + completion(); + } + }]; +} + +- (void)hideSpinner:(nullable void(^)(void))completion { + if (self.useStatusBarSpinner) { + [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + completion(); + return; + } + if ([self supportsAlertController]) { + [self hideModernSpinner:completion]; + } else { + [self hideIOS7Spinner:completion]; + } +} + +- (void)hideModernSpinner:(nullable void(^)(void))completion { + UIAlertController *pleaseWaitAlert = + objc_getAssociatedObject(self, + (__bridge const void *)kPleaseWaitAssociatedObjectKey); + + [pleaseWaitAlert dismissViewControllerAnimated:YES completion:completion]; + + objc_setAssociatedObject(self, + (__bridge const void *)(kPleaseWaitAssociatedObjectKey), + nil, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (void)hideIOS7Spinner:(nullable void(^)(void))completion { + UIWindow *pleaseWaitWindow = + objc_getAssociatedObject(self, + (__bridge const void *)kPleaseWaitAssociatedObjectKey); + + UIView *pleaseWaitView; + pleaseWaitView = pleaseWaitWindow.subviews.firstObject; + + [UIView animateWithDuration:0.5f animations:^{ + pleaseWaitView.layer.opacity = 0.0f; + } completion:^(BOOL finished) { + [pleaseWaitWindow resignKeyWindow]; + objc_setAssociatedObject(self, + (__bridge const void *)(kPleaseWaitAssociatedObjectKey), + nil, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + if (completion) { + completion(); + } + }]; +} + +@end + +@implementation SimpleTextPromptDelegate { + AlertPromptCompletionBlock _completionHandler; + SimpleTextPromptDelegate *_retainedSelf; +} + +- (instancetype)initWithCompletionHandler:(AlertPromptCompletionBlock)completionHandler { + self = [super init]; + if (self) { + _completionHandler = completionHandler; + _retainedSelf = self; + } + return self; +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + if (buttonIndex == alertView.firstOtherButtonIndex) { + _completionHandler(YES, [alertView textFieldAtIndex:0].text); + } else { + _completionHandler(NO, nil); + } + _completionHandler = nil; + _retainedSelf = nil; +} + +@end |