Call method before SWRevealViewController is shown - ios

I am using the SWRevealViewController plugins, it works great and I can navigate fine around the pages. My issue is that when the menu is being shown you can still interact with objects on the view that called the menu. I want to disable buttons from my view whilst the menu is shown. I am assigning the sidebar button using this code.
_sidebarButton.tintColor = [UIColor colorWithWhite:0.1f alpha:0.9f];
_sidebarButton.target = self.revealViewController;
_sidebarButton.tag=10;
_sidebarButton.action = #selector(revealToggle:);
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
I cannot work out how to call a function in my own class before the revealToggle action is fired. Any suggestions?

In MenuViewController (which is rear viewcontroller) write following:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.revealViewController.frontViewController.view setUserInteractionEnabled:NO];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.revealViewController.frontViewController.view setUserInteractionEnabled:YES];
}
then you can get each subview from this viewcontroller.
for example if frontviewcontroller is UINavigationController, you can do like this:
UINavigationController *navController = (UINavigationController *)self.revealViewController.frontViewController;
UIViewController *rootViewController = [navController.viewControllers firstObject];
NSArray *allViews = [NSArray arrayWithArray:(NSArray *)[rootViewController.view subviews]];

Related

How to switch between tabs and directly show pushed view controller?

This is my code:
VideoDetailViewController *VideoDetailVC = [self.storyboard instantiateViewControllerWithIdentifier:#"VideoDetailViewController"];
UINavigationController * navigationController = (UINavigationController *) [[self tabBarController] selectedViewController];
[self.tabBarController setSelectedIndex:0];
[navigationController pushViewController:VideoDetailVC animated:YES];
I am writing this code in tabbar's second index. I want to directly go to the Video Detail screen, which is child view controller of tabbar's zero index. Everything works fine but what I see is: it shows a parent view controller which is tabbar's zero index. After a second it pushes to the Video Detail screen. I just don't want to show the zero index. What is the solution? Help will be appreciated.
EDITED:
#import "TWPhotoCollectionViewCell.h"
#implementation TWPhotoCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.imageView.layer.borderColor = [UIColor blueColor].CGColor;
[self.contentView addSubview:self.imageView];
}
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.imageView.layer.borderWidth = selected ? 2 : 0;
}
#end
Replace below line
[navigationController pushViewController:VideoDetailVC animated:YES];
With
[navigationController pushViewController:VideoDetailVC animated:NO];
It may solve your issue.

SWRevealViewController - RightViewController

I'm using SWRevealViewController for implementing two side navigation views in my application. I followed the story board method and successfully implemented the rear view and front view. I tried setting right view exactly like the rear view via storyboard, but couldn't do it.
I have set the reveal view controller segue to "sw_right" but it looks like it is not being recognized by - (void)prepareForSegue:(SWRevealViewControllerSegue *)segue sender:(id)sender which is called twice for "sw_rear" and "sw_front"
What Am I missing?
- (void)prepareForSegue:(SWRevealViewControllerSegue *)segue sender:(id)sender
{
// $ using a custom segue we can get access to the storyboard-loaded rear/front view controllers
// the trick is to define segues of type SWRevealViewControllerSegue on the storyboard
// connecting the SWRevealViewController to the desired front/rear controllers,
// and setting the identifiers to "sw_rear" and "sw_front"
// $ these segues are invoked manually in the loadView method if a storyboard
// was used to instantiate the SWRevealViewController
// $ none of this would be necessary if Apple exposed "relationship" segues for container view controllers.
NSString *identifier = segue.identifier;
if ( [segue isKindOfClass:[SWRevealViewControllerSegue class]] && sender == nil )
{
if ( [identifier isEqualToString:SWSegueRearIdentifier] )
{
segue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc)
{
[self _setRearViewController:dvc animated:NO];
};
}
else if ( [identifier isEqualToString:SWSegueFrontIdentifier] )
{
segue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc)
{
[self _setFrontViewController:dvc animated:NO];
};
}
//This is never executed even after setting the identifier
else if ( [identifier isEqualToString:SWSegueRightIdentifier] )
{
segue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc)
{
[self _setRightViewController:dvc animated:NO];
};
}
}
}
here is the sample project , this is working fine I worked out for your self, the download link is
https://www.sendspace.com/file/0l2ndd
after downloaded the project u want to delete the project , use this link
https://www.sendspace.com/delete/0l2ndd/1b1bd537ad852b2fdea9b9a0cce3390f
here u were need the right swipe on the front view controller , add the UIBarButtonItem in the particular view Controller
#property (strong, nonatomic) IBOutlet UIBarButtonItem *rightIcon; //this is for left bar button Item
#property (nonatomic) IBOutlet UIBarButtonItem* revealButtonItem; //this is for right bar button Item
and add the some functions is View DidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
//action for left Swipe
[self.revealButtonItem setTarget: self.revealViewController];
[self.revealButtonItem setAction: #selector( revealToggle: )];
[self.navigationController.navigationBar addGestureRecognizer: self.revealViewController.panGestureRecognizer];
//action for Right Swipe
[self.rightIcon setTarget: self.revealViewController];
[self.rightIcon setAction: #selector( rightRevealToggle: )];
[self.navigationController.navigationBar addGestureRecognizer: self.revealViewController.panGestureRecognizer];
}
Swift
override func viewDidLoad() {
super.viewDidLoad()
//action for left Swipe
self.revealButtonItem.target = self.revealViewController
self.revealButtonItem.action = "revealToggle:"
self.navigationController.navigationBar.addGestureRecognizer(self.revealViewController.panGestureRecognizer)
//action for Right Swipe
self.rightIcon.target = self.revealViewController
self.rightIcon.action = "rightRevealToggle:"
self.navigationController.navigationBar.addGestureRecognizer(self.revealViewController.panGestureRecognizer)
}
I figured out what the problem was. In loadStoryboardControllers method [self performSegueWithIdentifier:SWSegueRightIdentifier sender:nil]; was commented out. If we implement right view controller this has to be uncommented.
You requested that I look at this thread.
I do not have experience with storyboards.
So, I am pasting below the code I have in my projects that allow for the Right Hand Side.
Take a look at the section I commented. Hopefully, this will set you on the right path.
Good luck
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window = window;
FrontViewController *frontViewController = [[FrontViewController alloc] init];
RearViewController *rearViewController = [[RearViewController alloc] init];
UINavigationController *frontNavigationController = [[UINavigationController alloc] initWithRootViewController:frontViewController];
UINavigationController *rearNavigationController = [[UINavigationController alloc] initWithRootViewController:rearViewController];
SWRevealViewController *revealController = [[SWRevealViewController alloc] initWithRearViewController:rearNavigationController frontViewController:frontNavigationController];
revealController.delegate = self;
// THIS SECTION RIGHT BELOW IS PROBABLY WHAT YOU WANT TO LOOK AT
RightViewController *rightViewController = rightViewController = [[RightViewController alloc] init];
rightViewController.view.backgroundColor = [UIColor greenColor];
revealController.rightViewController = rightViewController;
revealController.bounceBackOnOverdraw=NO;
revealController.stableDragOnOverdraw=YES;
self.viewController = revealController;
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
There is a try-catch condition between line on 435 to 444 on SWRevealViewController.m. Just rearrange the statement as following
[self performSegueWithIdentifier:SWSegueRightIdentifier sender:nil];
[self performSegueWithIdentifier:SWSegueFrontIdentifier sender:nil];
[self performSegueWithIdentifier:SWSegueRearIdentifier sender:nil];
Now my right-menu/rightViewController is working even though i am not using the leftmenu/rearViewController.
you can also do what shad suggested. But if you are getting a flag with the right you can just replace
- (void)loadStoryboardControllers
if ( self.storyboard && _rearViewController == nil )
{
//Try each segue separately so it doesn't break prematurely if either Rear or Right views are not used.
#try
{
[self performSegueWithIdentifier:SWSegueRearIdentifier sender:nil];
}
#catch(NSException *exception) {}
#try
{
[self performSegueWithIdentifier:SWSegueFrontIdentifier sender:nil];
}
#catch(NSException *exception) {}
#try
{
[self performSegueWithIdentifier:SWSegueRightIdentifier sender:nil];
}
#catch(NSException *exception) {}
}
}
with
- (void)loadStoryboardControllers
{
//[self performSegueWithIdentifier:SWSegueRightIdentifier sender:nil];
[self performSegueWithIdentifier:SWSegueFrontIdentifier sender:nil];
[self performSegueWithIdentifier:SWSegueRearIdentifier sender:nil];
}
as you can see i commented out
//[self performSegueWithIdentifier:SWSegueRightIdentifier sender:nil];
becasue thats the one giving you an issue. If its the front or rear you can do the same

Issue with adding buttons to UINavigationController

So this is how I make the navbar:
- (void)viewDidLoad
{
[super viewDidLoad];
UINavigationController *navBar = [[UINavigationController alloc] init];
[navBar willMoveToParentViewController:self];
navBar.view.frame = CGRectMake(0, 0, 320, 44);
[self.view addSubview:navBar.view];
[self addChildViewController:navBar];
[navBar didMoveToParentViewController:self];
...
And everywhere I have read says that this is how you add buttons:
UIBarButtonItem *button = [[UIBarButtonItem alloc]initWithTitle:#"test" style:UIBarButtonItemStyleBordered target:self action:#selector(print_message:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
But the button does not show on the navbar. What is wrong with this code?
Unless you're building a custom container view controller (which is a relatively rare thing to do), you should not be building a UINavigationController inside your content controller's -viewDidLoad. While it will provide you a navigation bar, your view controller parent-child relationship will be backwards: your content controller will contain the navigation controller, rather than the other way around.
Instead, you need to create the navigation controller earlier in your app's startup process - maybe in your application delegate, or in your main storyboard if you're using one. Make sure that the new navigation controller has your content controller as its root controller (usually by way of -initWithRootViewController:). Then your self.navigationItem configuration will work properly.
You should create your navigationbar probably differently:
In your xxxAppDelegate.m edit this method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
//This is the ViewController of the view you want to be the root
xxxViewController *tvc = [[xxxViewController alloc]init];
//Now you have to initialize a UINavigationController and set its RootViewController
UINavigationController *nvc = [[UINavigationController alloc]initWithRootViewController:tvc];
//Now set the RootViewController to the NavigationViewController
[[self window]setRootViewController:nvc];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
So now you have a proper NavigationController. If you do this in the viewDidLoad method, the NavigationController will be made each time you reload your view.
Now in your xxxViewController.m edit your init method:
- (id)init
{
...
if (self) {
//Create a UINavigationItem
UINavigationItem *n = [self navigationItem];
//Create a new bar button item
UIBarButtonItem *button = [[UIBarButtonItem alloc]initWithTitle:#"test" style:UIBarButtonItemStyleBordered target:self action:#selector(print_message:)];
[[self navigationItem]setRightBarButtonItem:button];
}
return self;
}
This should now display a proper NavigationBar with a UIBarButtonItem.

UINavigationController, how to hide tabbar in second level viewController then show tabbar in third level viewController

here is a piece of my code, but in this way, when I push the third level view controller, the tabbar won't show.
//at first level
SecondLevelViewController *_2vc = [[SecondLevelViewController alloc]initWithNibName:#"SecondLevelViewController" bundle:nil];
_2vc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:_2vc animated:YES];
//at second level
ThirdLevelViewController *_3vc = [[ThirdLevelViewController alloc]initWithNibName:#"ThirdLevelViewController" bundle:nil];
_3vc.hidesBottomBarWhenPushed = NO;
[self.navigationController pushViewController:_3vc animated:YES];
// Load the view
AddViewController *aController = [[AddViewController alloc] init];
// Set the view title
aController.title = #"Add View";
// hide tabbar
aController.hidesBottomBarWhenPushed = YES;
// add it to stack.
[[self navigationController] pushViewController:aController animated:YES];
-(void)viewWillAppear: (BOOL)animated
{
[super viewWillAppear:animated];
[self.tabBarController.tabBar setHidden:YES];
}
-(void)viewWillDisappear: (BOOL)animated
{
[super viewWillDisappear:animated];
[self.tabBarController.tabBar setHidden:NO];
}
Instead of setting the values of hidesBottomBarWhenPushed when you initialise the view controllers, you should instead handle the hiding mechanism in the -(void)viewWillAppear:(BOOL)animated in the view controllers instead.
An example of this implementation would be:
In SecondLevelViewController.m
-(void)viewWillAppear:(BOOL)animated
{
[_bottomBar setHidden:YES];
}
In ThirdLevelViewController.m
-(void)viewWillAppear:(BOOL)animated
{
[_bottomBar setHidden:NO];
}

Create uiTabBarController programmatically

I want to create a UIView for a UITabBarController
Here is my code for the .h file :
#interface TE : UIViewController <UITabBarControllerDelegate>{
UITabBarController *tabBarController;
}
#property (nonatomic,retain) UITabBarController *tabBarController;
#end
The viewDidLoad method:
UIViewController *testVC = [[T1 alloc] init];
UIViewController *otherVC = [[T2 alloc] init];
NSMutableArray *topLevelControllers = [[NSMutableArray alloc] init];
[topLevelControllers addObject: testVC];
[topLevelControllers addObject: otherVC];
tabBarController = [[UITabBarController alloc] init];
tabBarController.delegate = self;
[tabBarController setViewControllers:topLevelControllers animated:NO];
tabBarController.selectedIndex = 0;
self.view = tabBarController.view;
This creates the tab bar controller, but when I click on a tab bar item, I get an error:
Thread1:Program receive signal: SIGABRT
Edit: I solved the problem by downloading and modifying the version of http://www.iphonedevcentral.com/create-uitabbarcontroller/
You say above that you don't want to create the tabBarController in the appDelegate. Why not? Where else would you create it? The tabBarController has to be the root view controller and cannot be a child of any other view controller.
Btw, make sure you implement:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
NSUInteger tabIndex = [tabBarController.viewControllers indexOfObject:viewController];
if (viewController == [tabBarController.viewControllers objectAtIndex:tabIndex] ) {
return YES;
}
return NO;
}
Subclass UITabBarController
Override the - (void) loadView method and include the following code
MyCustomViewControllerOne* ctrl1 = [[[MyCustomViewControllerOne alloc] initWithNibName#"MyViewControllerOne" bundle: nil] autorelease];
UIViewController* ctrl2 = [[[UIViewController alloc] init] autorelease];
MyCustomControllerTwo* ctrl3 = [[[UIViewController alloc] initWithObject: myObj] autorelease];
ctrl1.title = #"First tab";
ctrl2.title = #"Second tab";
ctrl3.title = #"Third tab";
ctrl1.tabBarItem.image = [UIImage imageNamed:#"tab_image1.png"];
ctrl2.tabBarItem.image = [UIImage imageNamed:#"tab_image2.png"];
ctrl3.tabBarItem.image = [UIImage imageNamed:#"tab_image3.png"];
[self setViewControllers: #[ctrl1, ctrl2, ctrl3]];
That's pretty much it.
Change self.view = tabBarController.view; to
[self.view addSubview:tabBarController.view]; And it works correctly
Trying changing
self.view = tabBarController.view;
to
[self.view addSubview:tabBarController.view];
See if that helps.
Also try placing this in your -(void)loadView method
- (void)loadView {
UIView *mv = [[UIView alloc] initWithFrame:CGRectMake(0.0, 100.0, 320.0, 480.0)];
self.view = mv;
[mv release];
}
The reason you probably are experiencing a black screen is because you haven't initialized your UIView properly.
#Mehdi, just make your TE a UITabBarController instead of a UIViewController which then has a TabBarController in it. Makes it all the more easy to manage your TabBarController. To respond to some others who have indicated that you can have only one TabBarController as the window's rootViewController. That is not the case. A UITabBarController can be instantiated in multiple places where you need a second level menu navigation. Have a TabBar within a TabBar would not make sense, but having a left Navigation Menu and then having a TabBar on each menu item would make sense.

Resources