Question

I'm working on a iOS Application and i use Google drive to access my files , login and listing file works fine , but I'm just asking how i can add a cancel button on the Login interface provided by Google drive sdk see the Image bellow

enter image description here

As,you see there are no way to do a cancel or a go back button.

Here Is my code

// verify if the user is already connected or not 
    - (void)checkIfIsConnected
    {
        // Check for authorization.
        GTMOAuth2Authentication *auth =
        [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
                                                              clientID:kClientID
                                                          clientSecret:kClientSecret];
        if ([auth canAuthorize]) {
            [self isAuthorizedWithAuthentication:auth];
        }else
        {
            [self ConnectToDrive];
        }
    }

    - (GTLServiceDrive *)driveService {
        static GTLServiceDrive *service = nil;
        if (!service) {

            service = [[GTLServiceDrive alloc] init];
            // Have the service object set tickets to fetch consecutive pages
            // of the feed so we do not need to manually fetch them.
            service.shouldFetchNextPages = YES;
            // Have the service object set tickets to retry temporary error conditions
            // automatically.
            service.retryEnabled = YES;
        }
        return service;
    }

    -(void) ConnectToDrive{
        SEL finishedSelector = @selector(viewController:finishedWithAuth:error:);
        GTMOAuth2ViewControllerTouch *authViewController =
        [[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
                                                   clientID:kClientID
                                               clientSecret:kClientSecret
                                           keychainItemName:kKeychainItemName
                                                   delegate:self
                                           finishedSelector:finishedSelector];
        [self.fileManagementViewController presentModalViewController:authViewController animated:YES];
    }

    // Action executed after finishing the Authentication
    - (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
          finishedWithAuth:(GTMOAuth2Authentication *)auth
                     error:(NSError *)error {
        [self.fileManagementViewController dismissModalViewControllerAnimated:YES];
        if (error == nil) {
            [self isAuthorizedWithAuthentication:auth];
        }
    }

    - (void)isAuthorizedWithAuthentication:(GTMOAuth2Authentication *)auth {
        [[self driveService] setAuthorizer:auth];
        self.isAuthorized = YES;
        [self loadDriveFiles];
    }

so what wrong ??

Was it helpful?

Solution

Please follow the steps -

enter image description here

Go to--> GTLSource->Common->OAuth2->Touch-->GTMOAuth2ViewControllerTouch.m

-(void)viewDidLoad
{
[self setUpNavigation];

[self.navigationController.navigationBar setTitleTextAttributes:@   {NSForegroundColorAttributeName : [UIColor blueColor]}];
self.navigationController.navigationBar.translucent = NO;

UINavigationBar *naviBarObj = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 320, 63)];
[self.view addSubview:naviBarObj];

UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc]initWithTitle:[NSString stringWithFormat:NSLocalizedString(@"Cancel", nil)] style:UIBarButtonItemStyleBordered target:self
                                                             action:@selector(cancelGdriveSignIn:)];    
UINavigationItem *navigItem = [[UINavigationItem alloc] initWithTitle:@"Google Drive"];
navigItem.rightBarButtonItem = cancelItem;
naviBarObj.items = [NSArray arrayWithObjects: navigItem,nil];    
}

 -(void)cancelGdriveSignIn:(id)sender
 {
  [self dismissViewControllerAnimated:YES completion:^(void){}];
 }

-(void)setUpNavigation // Default Method Available 
{
 rightBarButtonItem_.customView = navButtonsView_;
 self.navigationItem.rightBarButtonItem = rightBarButtonItem_;
}

Once you add the above changes in the GTMOAuth2ViewControllerTouch.m and run it. you will get cancel button like this-

enter image description here

Happy Coding......!!

OTHER TIPS

Change sources - bad way. Here is my solution. Works on iPhone and iPad

 GTMOAuth2ViewControllerTouch *authViewController = [GTMOAuth2ViewControllerTouch controllerWithScope:kGTLAuthScopeDrive
                                                                                                clientID:GoogleDriveClientID
                                                                                            clientSecret:GoogleDriveClientSecret
                                                                                        keychainItemName:GoogleDriveKeychainItemName
                                                                                       completionHandler:authCompletionHandler];

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:authViewController];
    navigationController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [rootController presentViewController:navigationController animated:YES completion:nil];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", nil)
                                                                         style:UIBarButtonItemStylePlain
                                                                        target:self
                                                                        action:@selector(didCanceledAuthorization)];
        authViewController.navigationItem.rightBarButtonItem = nil;
        authViewController.navigationItem.leftBarButtonItem = cancelButton;
        authViewController.navigationItem.title = @"Google Drive";
    });

Swift Version - For the new users : This will not hide the Google logo under the navigationBar

Extend the class GTMOAuth2ViewControllerTouch

extension GTMOAuth2ViewControllerTouch
{
    public override func viewDidLoad()
    {
        super.viewDidLoad()
        let cancelItem = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: #selector(self.cancelGdriveSignIn))
        self.navigationController?.navigationBar.topItem?.rightBarButtonItem = cancelItem
        self.navigationController?.navigationBar.topItem?.title = "Google Drive"
    }

    func cancelGdriveSignIn()
    {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}

AND add a navigation Controller before returning your AuthController

private func createAuthController() -> UIViewController {
    let scopeString = scopes.joinWithSeparator(" ")
    let controller = GTMOAuth2ViewControllerTouch(scope: scopeString, clientID: kClientID, clientSecret: nil, keychainItemName: kKeychainItemName, delegate: self, finishedSelector: #selector(ViewController.viewController(_:finishedWithAuth:error:)))
    let navController = UINavigationController(rootViewController: controller)
    return navController
}

Works like charm.

I'm Agree with @nab0y4enko - change the SDK is bad.

1.The current GTMOAuth2ViewControllerTouch add 2 buttons to the navigation bar. So I had to create new class "CustomAuthViewController" which inherited from GTMOAuth2ViewControllerTouch and override setUpNavigation with no implementation.This implementation will not add those 2 buttons

@implementation CustomAuthViewController

- (void)setUpNavigation
{
    // Don't call super becasue it is adding ugly Back / Forwad image buttons
}

@end

2.We can set the cancel button without declare and change the navigation width, and without dispatch async thread. We can do it by edit the navigationBar.topItem instead of the navigation item.

UIViewController* navController = [self createAuthNavigationController];
[self.originViewController presentViewController:navController animated:YES completion:nil];

- (UIViewController *)createAuthNavigationController
{
    // Create CustomViewController which inherited from GTMOAuth2ViewControllerTouch
    CustomAuthViewController * authViewController = [[CustomAuthViewController alloc] initWithScope:kGTLAuthScopeDrive
                                      clientID:kClientID
                                  clientSecret:kClientSecret
                              keychainItemName:kKeychainItemName
                                      delegate:self
                              finishedSelector:@selector(viewController:finishedWithAuth:error:)];

    // Create navigation VC
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:authViewController];

    // Set as Modal form -> not full screen in IPad
    [navController setModalPresentationStyle:UIModalPresentationFormSheet];

    // Add cancel button to the navigation
    navController.navigationBar.topItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 
                                          target:self
                                          action:@selector(buttonCancelTapped:)];;
    // Set Title
    [navController.navigationBar.topItem setTitle:@"Google Drive"];

    return navController;
}  

The Immi's answer is good. But for those, who has iPad problem:

nav Bar's width is hardcoded as 320.

You should make the width correct, so replace the:

    UINavigationBar *naviBarObj = [[UINavigationBar alloc] initWithFrame:CGRectMake(0., 0., 320., 63.)];

with this

    UINavigationBar *naviBarObj = [[UINavigationBar alloc] initWithFrame:CGRectMake(0., 0., [[UIScreen mainScreen] bounds].size.width, 63.)];

Also the Google title is hidden by navigation Bar. Not good. So do the next: In

- (void)moveWebViewFromUnderNavigationBar change

  CGRect webFrame = CGRectMake(0., 63., self.view.frame.size.width, self.view.frame.size.height);

and in

- (void)viewWillAppear:(BOOL)animated 

comment out calling of method [self isNavigationBarTranslucent] :

//    if ([self isNavigationBarTranslucent]) {
  [self moveWebViewFromUnderNavigationBar];
//    }

UPD. for interface orientation To make the navBar change due to interface orientation, I recommend to use NSNotification Center, see this answer. As for this situation, you should do the next:

  1. Implement your NavBar in @interface in GTMOAuth2ViewControllerTouch.m
  2. Put the notification listener in ViewDidLoad.
  3. Make the navBar change.

So, let's go:

  1. right under @interface put @property (nonatomic, strong) UINavigationBar *naviBarObj;

  2. in ViewDidLoad:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChangeNotification:) name:UIDeviceOrientationDidChangeNotification object:nil];

  3. and finally:

    -(void)deviceOrientationDidChangeNotification:(NSNotification*)note
    {
        UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
        if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown)
        {
            self.naviBarObj.frame = CGRectMake(0., 0., [[UIScreen mainScreen] bounds].size.width, 63.0);
        }
        else if (orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft)
        {
            self.naviBarObj.frame = CGRectMake(0., 0., [[UIScreen mainScreen] bounds].size.height, 63.0);
        } }
    

P.S. don't forget, that you should now use self.naviBarObj everywhere you used naviBarObj. And remove the UINavigationBar before naviBarObj in ViewDidLoad

UPD 2.0

  - (CGRect) setNavBarWidth
{
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown)
    {
        return CGRectMake(0., 0., [[UIScreen mainScreen] bounds].size.width, 63.0);
    }
    else if (orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft)
    {
        return CGRectMake(0., 0., [[UIScreen mainScreen] bounds].size.height, 63.0);
    }

    return CGRectMake(0., 0., [[UIScreen mainScreen] bounds].size.width, 63.0);
}

And call it self.naviBarObj = [[UINavigationBar alloc] initWithFrame:[self setNavBarWidth]]; from viewDidLoad, as well as

self.naviBarObj.frame = [self setNavBarWidth];

from deviceOrientationDidChangeNotification methods then :)

    let finishedSelector = #selector(YourViewControllerOrAnotherObject.googleAuthViewController(_:finishedWithAuth:error:))
    let authController = GTMOAuth2ViewControllerTouch(scope: kGTLAuthScopeDriveReadonly, clientID: AppGoogleClientID, clientSecret: nil, keychainItemName: keychainItemName, delegate: self, finishedSelector: finishedSelector)
    let cancelAction = #selector(YourViewControllerOrAnotherObject.dismissGoogleAuthController)
    authController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: cancelAction)
    authController.title = "Google Authentication"

    let navigationController = UINavigationController(rootViewController: authController)
    self.presentViewController(navigationController, animated: true, completion: { () -> Void in
        // remove default rightBarButtonItem
        authController.navigationItem.rightBarButtonItem = nil
    })
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top