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
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 ??
Please follow the steps -
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-
Happy Coding......!!
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.
The Immi's answer is good. But for those, who has iPad problem:
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:
- Implement your NavBar in @interface in GTMOAuth2ViewControllerTouch.m
- Put the notification listener in ViewDidLoad.
- Make the navBar change.
So, let's go:
right under @interface
put
@property (nonatomic, strong) UINavigationBar *naviBarObj;
in ViewDidLoad:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(deviceOrientationDidChangeNotification:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
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 :)
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;
}
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
})