aboutsummaryrefslogtreecommitdiffhomepage
path: root/AuthSamples/Sample/UIViewController+Alerts.m
diff options
context:
space:
mode:
authorGravatar Paul Beusterien <paulbeusterien@google.com>2017-05-15 12:27:07 -0700
committerGravatar Paul Beusterien <paulbeusterien@google.com>2017-05-15 12:27:07 -0700
commit98ba64449a632518bd2b86fe8d927f4a960d3ddc (patch)
tree131d9c4272fa6179fcda6c5a33fcb3b1bd57ad2e /AuthSamples/Sample/UIViewController+Alerts.m
parent32461366c9e204a527ca05e6e9b9404a2454ac51 (diff)
Initial
Diffstat (limited to 'AuthSamples/Sample/UIViewController+Alerts.m')
-rw-r--r--AuthSamples/Sample/UIViewController+Alerts.m346
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