Search code examples
iphoneiosobjective-cuinavigationbaruinavigationitem

set custom back bar button universally with no title


I want to set custom back bar button for all controllers in the app. I tried using this:

[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

It sets the image. That's OK. But, what i really want to do is that, i just want a custom button for back bar button which does not contain any title etc. The code above works, but it adds automated titles and resizes the back bar button item. My need is to have a fixed frame, no-title back bar button item for all controllers in the app.


Solution

  • I've resolved it. Just make a category over UIViewController and import it in prefix.pch file. Then write a method: customViewWillAppear: and swizzle it with viewWillAppear method:

    +(void)load{
    
    Method viewWillAppear = class_getInstanceMethod(self, @selector(customViewWillAppear:));
    
    Method customViewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:));
    method_exchangeImplementations(viewWillAppear, customViewWillAppear);
    

    }

    Add the above method to that category class. Then implement your customViewWillAppear method like this:

    -(void)customViewWillAppear:(BOOL)animated{
        [self customViewWillAppear:animated];
        if([self.navigationController.viewControllers indexOfObject:self] != 0  && !self.navigationItem.hidesBackButton){
            UIBarButtonItem *cancelBarButton = nil;
            UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
            [cancelButton addTarget:self action:@selector(popViewControllerWithAnimation) forControlEvents:UIControlEventTouchUpInside];
            [cancelButton setBackgroundImage:[UIImage imageNamed:@"yourImage.png"] forState:UIControlStateNormal];
            [cancelButton sizeButtonToFit];
    
            cancelBarButton = [[UIBarButtonItem alloc] initWithCustomView:cancelButton];
    
            NSMutableArray * leftButtons = [NSMutableArray arrayWithObject:cancelBarButton];
            [leftButtons addObjectsFromArray:self.navigationItem.leftBarButtonItems];
            [self.navigationItem setLeftBarButtonItem:nil];
            [self.navigationItem setLeftBarButtonItems:leftButtons];
        }
    
        [self.navigationItem setHidesBackButton:YES];
    }
    -(void)popViewControllerWithAnimation{
        [self.navigationController popViewControllerAnimated:YES];
    }
    

    Now, for every controller in your code, you have a custom back button. This took me a lot of time to implement and figure out. Hope it'll help you guys all too.

    EDIT: Please use the following code to support iOS7> back swipe feature;

    UIImage *image = [UIImage imageForName:@"some_image"];
    navBar.backIndicatorImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    navBar.backIndicatorTransitionMaskImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    

    Create a base view controller and add the following code;

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
    }