10

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 ??

ChenSmile
  • 3,401
  • 4
  • 39
  • 69

6 Answers6

24

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......!!

ChenSmile
  • 3,401
  • 4
  • 39
  • 69
  • thanks for you reply , but can you give me the exact path to the GTMOAuth2Authentication.m class , because for me i found it in GTL source/Common/OAuth2 but i did not find the viewDidLoad Function on it –  Jan 31 '14 at 12:30
  • I do not have GTMOAuth2Authentication.m on the GTLSource->Common->OAuth2->Touch but i have only GTMOAuth2ViewControllerTouch.m and i did that in it but nothing changed –  Jan 31 '14 at 13:38
  • @hatimhaffane buddy check here---- GTLSource->Common->OAuth2->Touch-->GTMOAuth2ViewControllerTouch.m. See my updated answer.. – ChenSmile Jan 31 '14 at 13:42
  • please see my Edit , may be i missing some thing –  Jan 31 '14 at 14:04
  • @hatimhaffane please follow the path....GTLSource->Common->OAuth2->Touch-->GTMOAuth2Authentication.m. Edit the code in GTMOAuth2Authentication.m. – ChenSmile Feb 03 '14 at 04:22
  • i did that but i did not get the navigation bar –  Feb 03 '14 at 10:12
  • BTW there are no need to the diagram i know where is the class that you told me and i edit it but nothing happened , thanks for your help –  Feb 03 '14 at 10:15
  • the code that i show to you exist on my project class not on the GTMOAuth2ViewControllerTouch.m , do you have any idea how i can debug the sdk calls from my project ? –  Feb 03 '14 at 10:23
  • it's works Bro :) i just opened the workspace containing my Project and the SDK project and clean it then build it thanks a lot for your patient –  Feb 03 '14 at 10:33
12

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";
    });
nab0y4enko
  • 369
  • 3
  • 5
4

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.

Amit Singh
  • 2,698
  • 21
  • 49
  • I just needed to change the title and it worked only when invoked in viewDidAppear() not in viewDidLoad() in the above code. Otherwise thanks for posting this. – petrsyn Jan 12 '17 at 12:24
3

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;
}  
Elihay
  • 123
  • 1
  • 5
2

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 :)

Community
  • 1
  • 1
Aleksey Potapov
  • 3,683
  • 5
  • 42
  • 65
  • good but when i move from portrait landscape the navigation bar don't take the howl screen –  Mar 20 '14 at 11:10
  • with this update when you change orientation the navigation bar works fine , but if you start the app on the landscape by default the navigation bar will not take the howl size :) –  Mar 20 '14 at 13:46
2
    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
    })
xinatanil
  • 1,085
  • 2
  • 13
  • 23