iOS TabBarController: run check before entering new tab - ios

I have an app which contains a UITabBarController. The last tab should only be entered when a condition is met. Currently I am checking this condition at the function viewDidAppear. But is it also possible to do this check every time before the tab is opened and displayed?
According to the first response I added this two files:
MainTabBarController.h
#import <UIKit/UIKit.h>
#interface MainTabBarController : UITabBarController
#end
MainTabBarController.m
#import "MainTabBarController.h"
#interface MainTabBarController ()
#end
#implementation MainTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)viewController
{
NSUInteger indexOfTab = [theTabBarController.viewControllers indexOfObject:viewController];
if(indexOfTab == 2)
{
NSLog(#"Is it working?");
}
}
#end

In MainTabBarController.m file,add a delegate
#interface MainTabBarController ()<UITabBarControllerDelegate>
Then in viewDidLoad, add
self.delegate = self;
Then add a method:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController: (UIViewController *)viewController
{
//add your check here
return YES;
}

is it also possible to do this check every time before the tab is
opened and displayed?
You need to override the UITabBarController delegate method for this :
- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)viewController {
NSUInteger indexOfTab = [theTabBarController.viewControllers indexOfObject:viewController];
if(indexofTab == yourTabIndexToMetCondition){
// Do your stuff here
}
}

Related

prepareForSegue is not getting called

i created three scenes, each of them has a button and a label as shown in image-1. Scene1 is linked to Scene2 through "Show Segue called scene1To2"
,Scene2 is linked to scene3 through "Show Segue called scene2To3" and finally Scene3 is linked to scene1 through "Show Segue called scene3To1".
I am trying to to call "prepareForSegue" when the button in scene1 is clicked, so I wrote the code shown in code1 section below..
but when i run the code the NSLog message "NSLog(#"transiting from scene1To2");" does not show up
please let me know why the NSLog message doesn't show
code1:
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a
//nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)from1To2:(id)sender {
NSLog(#"Hi");
[self performSegueWithIdentifier:#"scene1To2" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue
{
if ([segue.identifier isEqualToString:#"scene1To2"])
{
NSLog(#"transiting from scene1To2");
}
}
#end
Your method signature is wrong. See if this does the trick:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"scene1To2"])
{
NSLog(#"transiting from scene1To2");
}
}
In your Segue links on the storyboard have you added the segue name to the segue identifier?
You can use something like this, you import the scene1To2 controller.
scene1To2 *view = [[UIStoryboard storyboardWithName:#"YOUR_STORYBOARD" bundle:nil] instantiateViewControllerWithIdentifier:#"scene1To2"];
[self presentViewController:view animated:YES completion:nil];
then you go to the other view controller

Enable back back swipe gesture when using custom navigation controller

I've got a custom navigation controller declared as below. My problem is that once I implement this, the back swipe gesture to go back to previous stack (interactivepopgesturerecognizer) is not working. How can I enable it back? I've got a lot of view controller in my app. Thank You.
#import "NavController.h"
#interface NavController ()
{
BOOL shouldIgnorePushingViewControllers;
}
#end
#implementation NavController
-(instancetype)init {
self = [super init];
self.delegate=self;
return self;
}
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (!shouldIgnorePushingViewControllers)
{
[super pushViewController:viewController animated:animated];
}
shouldIgnorePushingViewControllers = YES;
}
- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
shouldIgnorePushingViewControllers = NO;
}
#end
Try to enable property
self.interactivePopGestureRecognizer.enabled = YES;
to init method

UINavigationController Broken in IOS 8?

I have a series of UIViewControllers in my app, and these are presented using a UINavigationController. The HOME ViewController calls pushViewController to get to the PROFILES ViewController. The PROFILES screen correctly shows the back button to HOME. Then selecting a button on PROFILES will take the user to the DETAIL ViewController. The DETAIL screen correctly shows the back button to PROFILES. But when I press the back button to PROFILES, I do indeed go back to the PROFILES screen but the navigation bar on that screen now shows the title HOME with no back button. In other words, it appears that IOS 8 has popped the ViewController once to go back from DETAIL to PROFILES, but has somehow popped the navigation bar items twice!
Any idea how I can fix this?
Apparently the solution outline can be found here:
UINavigationController and UINavigationBarDelegate.ShouldPopItem() with MonoTouch
In my solution, I just have all my view controllers extend CustomUINavigationController, which looks like this:
#import "CustomUINavigationController.h"
#import "IOSVersion.h"
#interface CustomUINavigationController ()
#end
#implementation CustomUINavigationController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.delegate=self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//
// The following two methods are the key to overriding the buggy behavior in IOS 8
// The first method is from here:
// https://stackoverflow.com/questions/6413595/uinavigationcontroller-and-uinavigationbardelegate-shouldpopitem-with-monotouc
//
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
NSLog(#"Inside shouldPopItem");
if (regularPop) {
NSLog(#"regularPop is TRUE");
} else {
NSLog(#"regularPop is FALSE");
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
if (regularPop) {
regularPop = FALSE;
return YES;
}
regularPop = TRUE;
[self popViewControllerAnimated:YES];
return NO;
} else {
return [super navigationBar:navigationBar shouldPopItem:item];
}
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
NSLog(#"Inside popViewControllerAnimated");
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
int cnt=(int)[viewControllers count];
NSLog(#"Inside popViewControllerAnimated, cnt is %d",cnt);
UIViewController *vc=[viewControllers objectAtIndex:cnt-2];
if (regularPop) self.desiredVC=vc;
[self popToViewController:vc animated:animated];
return vc;
} else {
return [super popViewControllerAnimated:animated];
}
}
- (UIViewController *)manualpopViewControllerAnimated:(BOOL)animated {
NSLog(#"Inside manualpopViewControllerAnimated");
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
regularPop=TRUE;
return [self popViewControllerAnimated:animated];
} else {
return [super popViewControllerAnimated:animated];
}
}
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
NSLog(#"Inside didShowViewController");
if (viewController==self.desiredVC) {
NSLog(#"Inside didShowViewController, found desiredVC");
regularPop = FALSE;
}
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end

passing data from view controller to another

i have to view controllers .. and i want to pass data from the first to the second view i have this code
for the ViewController.h
#import <UIKit/UIKit.h>
#import "SecondView.h"
#interface ViewController : UIViewController{
SecondView *secondviewData;
IBOutlet UITextField *textfield;
}
#property (nonatomic,retain) SecondView *secondviewData;
-(IBAction)passdata:(id)sender;
#end
for the viewController.m
#import "ViewController.h"
#import "SecondView.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize secondviewData;
-(IBAction)passdata:(id)sender{
SecondView *second= [[SecondView alloc] initWithNibName:nil bundle:nil];
self.secondviewData=second;
secondviewData.passedValue=textfield.text;
[self presentModalViewController:second animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
for the second view controller which is SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIViewController{
IBOutlet UILabel *label;
NSString *passedValue;
}
#property (nonatomic,retain) NSString *passedValue;
-(IBAction)back:(id)sender;
#end
for the SecondView.m
#import "SecondView.h"
#import "ViewController.h"
#interface SecondView ()
#end
#implementation SecondView
#synthesize passedValue;
-(IBAction)back:(id)sender{
ViewController *vc= [[ViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:vc animated:YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
label.text=passedValue;
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
the error I'm having is presentModalViewController deprecated iOS 6 in these 2 lines
[self presentModalViewController:vc animated:YES];
[self presentModalViewController:vc animated:YES];
and when i run it and click on the button it will stop working and displays a blank black page
You can save data in AppDelegate to access it across view controllers in your application. All you have to do is create a shared instance of AppDelegate
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
If you are building for >= iOS 5 then you should be using presentViewController:animated:completion: instead of presentModalViewController:animated:.
Also, the idea of 'back' doesn't usually mean pushing something new. So, this code:
- (IBAction)back:(id)sender {
ViewController *vc= [[ViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:vc animated:YES];
}
should change to:
- (IBAction)back:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Now, you should look at using a delegate pattern to pass the data back to the originating view controller. And preferably that delegate implementation would include telling the delegate that the second controller is finished and the delegate triggers the dismiss.
See Passing Data between View Controllers

How to change to a view controller programmatically?

I want to transition to a view I made in the main.storyboard, when they enter the password correctly.
How do I do this?
I need it to pull up the view I already created. I want a transition in the code block -(void) unlock.
Code
//
// ViewController.m
// Login
//
// Created by Ben Rosen on 5/24/14.
// Copyright (c) 2014 Ben Rosen. All rights reserved.
//
#import "ViewController.h"
#import "UnlockedScreen.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)login:(id)sender
{
NSString *correctUser = #"money";
NSString *correctPassword = #"ilovemoney";
if ((usernameTextField.text == correctUser)==YES && (passwordTextField.text = correctPassword)==YES)
{
[self unlock];
}
}
-(void) unlock
{
// here should be the transition
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#end
In you storyboard, go on your first view controller, press CTRL click on the viewController and release the mouse (and CTRL) on the destination view controller.
Now choose type of segue (push if you are in a navigationController otherwise modal) and choose an identifier on the inspector for this trigger.
In your code:
-(IBAction)login:(id)sender
{
NSString *correctUser = #"money";
NSString *correctPassword = #"ilovemoney";
if ([usernameTextField.text isEqualToString:correctUser] && [passwordTextField.text isEqualToString:correctPassword])
{
[self performSegueWithIdentifier:#"name" sender:sender];
}
}
As you see i changed your if statement..your compare was wrong.
[self unlock];
remove it and write this method
[self performSegueWithIdentifier:#"profileSegue" sender:self] ;
in the storyboard name to identifier(profileSegue) on the inspector
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"profileSegue"]) {
ProfileViewController *profileViewController = segue.destinationViewController;
profileViewController.isFromDealView = YES;
profileViewController.hidesBottomBarWhenPushed = YES;
}
Instantiate your viewController with the identifier you have provided for your viewController.
-(void) unlock
{
// here should be the transition
UIViewController *vc = [[UIStoryboard storyboardWithName:#"storyboardname" bundle:nil] instantiateViewControllerWithIdentifier:#"viewControllersID"];
[self presentViewController:vc animated:YES completion:nil];
}

Resources