I'm trying to develop an app (game) with this architecture:
Main view is a naviagtioncontroller based with navbar hidden
in Main view I need a light info
button to show a options/credits
flipsideview
this flipsideview must have another
navigationcotroller with a right bar
button to a "Done" system button
The problem is that the flipsideview doesn't show the done button and it seems to show the Main navigation controller...
This is the code.
AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Main View (loaded from a XIB). Extract only of showInfo:
-(IBAction) showInfo:(id)sender {
FlipSideViewController *controller = [[FlipSideViewController alloc] initWithNibName:#"FlipSideView" bundle:nil];
controller.delegate = self;
controller.title = #"Info";
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
navController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
navController.navigationBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonItemStyleDone
target:controller action:#selector(done:)];
navController.navigationItem.rightBarButtonItem = doneButton;
controller.navController = navController;
[self presentModalViewController:navController animated:YES];
[doneButton release];
[controller release];
[navController release];
}
- (void)flipsideViewControllerDidFinish:(FlipSideViewController *)controller {
[self dismissModalViewControllerAnimated:YES];
}
FlipSideView. In the XIB I've only a blank view with outlet linked to the UIViewController view.
#protocol FlipsideViewControllerDelegate;
#interface FlipSideViewController : UIViewController {
id <FlipsideViewControllerDelegate> delegate;
UINavigationController *navController;
}
#property (nonatomic,assign) id <FlipsideViewControllerDelegate> delegate;
#property (nonatomic,retain) UINavigationController *navController;
-(IBAction)done;
#end
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipSideViewController *)controller;
#end
}
Implementation file...
- (void)viewDidLoad
{
[super viewDidLoad];
self.navController.navigationItem.title = #"Pippo";
}
#pragma mark - User Methods
- (IBAction)done {
[self.delegate flipsideViewControllerDidFinish:self];
}
The result is:
Main View showing without navigation
bar
Click on info button
Flipsideview showing with animation
and navigation bar with title "Info" and not "pippo
and not "Done" button on the right...
Where am I wrong??
Don't you get two navigationBar with navigationItems on FlipsideViewController? I am fighting with this bug now.
Related
I have 2 UIViewControllers and want to have UINavigationController with UINavigationBar & UINavigationItem on them. But my code doesn't working ..
here is my code :
#import "testView1.h"
#import "testView2.h"
#interface testView1 ()
#end
#implementation testView1
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor darkGrayColor];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self];
testView2 *detail = [testView2 new];
[navController pushViewController:detail animated:YES];
}
Try to embed navigation controller in storyboard as below :
First select your testView1 in storyboard .
Select Navigation Controller
And Changes as below
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
/// testView2 *detail = [testView2 new];
testView2 *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"testView2 Identifier"]; // if you have add controller in storyboard
[self.navigationController pushViewController:detail animated:YES];
}
You won't see the first View Controller because you already push the second view controller upon the navigation controller.
I have 1 UITabbarController with 3 ViewControllers belong to its named aVC-bVC-cVC(VC = ViewController). Then I have 1 MenuSideBar have others 3 ViewControllers named dVC-eVC-fVC.
All I want is whenever I push to dVC or eVC or fVC my UITabbarController always display. How I can do that ? I really stuck at this point. I have to try many ways even custom a tabbarController myself but still not working.
Please help me. I really need help on this case.
Very thank you.
I have made the sample demo for you in Objective C using SWRevealViewController as you had tagged that in your question. I have used the XCode 7.1.1 version. Make sure to open this demo in 7.x versions of XCode. This problem can also be solved by other side menu libraries like MFSideMenu etc
Here is the link of the demo sample made by me according to your requirements.
https://github.com/RajanMaheshwari/TabBarControllerApp
EXPLANATION:
In order to keep a tab bar always in your app you have to add a TabBar on every controller which is not a added viewController of UITabBarController. In my sample demo I have taken the various Controllers
1.LeftSideViewController - which will be the left side panel for whole app.
2.MainTabBarViewController - which will be the UITabBarController subclass and it will be connected to two other view controllers which will be the part of MainTabBarViewController.
----a.TabFirstViewController
----b.TabSecondViewController
3.FirstViewController- which will be the one that will from LeftSideViewController's table view and has its own UITabBar added.
4.SecondViewController- which will be the one that will from LeftSideViewController's table view and has its own UITabBar added.
Import the SWRevealViewController folder.
In your AppDelegate's didFinishLaunchingWithOptions method we need to make the root view controller as the MainTabBarViewController.
AppDelegate.h
#import <UIKit/UIKit.h>
#import "SWRevealViewController.h"
#interface AppDelegate : UIResponder<UIApplicationDelegate,SWRevealViewControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) SWRevealViewController *viewController;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "LeftSideViewController.h"
#import "SWRevealViewController.h"
#import "MainTabBarViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//Here Adding some notification observers which will be fired whenvever a tabbar index in clicked of the viewcontrollers whose parent is not UITabBarController class and the left side menu ones too.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(backToTabIndexControllerFirst) name:#"backToTabIndexControllerFirst" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(backToTabIndexControllerSecond) name:#"backToTabIndexControllerSecond" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(firstVCWithoutNAV) name:#"firstVCWithoutNAV" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(secondVCWithoutNAV) name:#"secondVCWithoutNAV" object:nil];
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window = window;
UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:#"LeftSideViewController"];
MainTabBarViewController *mainTabBarController = [storyBoard instantiateViewControllerWithIdentifier:#"MainTabBarViewController"];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:leftSideController frontViewController:mainTabBarController];
mainRevealController.delegate = self;
self.viewController = mainRevealController;
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
Methods Definations of all observers added
AppDelegate.m
-(void)firstVCWithoutNAV{
self.window.rootViewController = nil;
UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController * firstVC = [storyBoard instantiateViewControllerWithIdentifier:#"FirstNAV"];
LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:#"LeftSideViewController"];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:leftSideController frontViewController:firstVC];
mainRevealController.delegate = self;
self.viewController = mainRevealController;
self.window.rootViewController = self.viewController;
}
-(void)secondVCWithoutNAV{
self.window.rootViewController = nil;
UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController * secondVC = [storyBoard instantiateViewControllerWithIdentifier:#"SecondNAV"];
LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:#"LeftSideViewController"];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:leftSideController frontViewController:secondVC];
mainRevealController.delegate = self;
self.viewController = mainRevealController;
self.window.rootViewController = self.viewController;
}
-(void)backToTabIndexControllerFirst{
UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:#"LeftSideViewController"];
MainTabBarViewController *mainTabBarController = [storyBoard instantiateViewControllerWithIdentifier:#"MainTabBarViewController"];
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:leftSideController frontViewController:mainTabBarController];
mainRevealController.delegate = self;
self.viewController = mainRevealController;
self.window.rootViewController = self.viewController;
}
-(void)backToTabIndexControllerSecond{
UIStoryboard* storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LeftSideViewController *leftSideController = [storyBoard instantiateViewControllerWithIdentifier:#"LeftSideViewController"];
MainTabBarViewController *mainTabBarController = [storyBoard instantiateViewControllerWithIdentifier:#"MainTabBarViewController"];
//To make selected index as the one which is clicked from tab bar
mainTabBarController.selectedIndex = 1;
SWRevealViewController *mainRevealController = [[SWRevealViewController alloc]
initWithRearViewController:leftSideController frontViewController:mainTabBarController];
mainRevealController.delegate = self;
self.viewController = mainRevealController;
self.window.rootViewController = self.viewController;
}
In the Controllers which have no UITabBarController parent class, we will add a tabBar and set tabBar's delegate to self and add the tabBar's didSelectItem delegate method.
FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController<UITabBarDelegate>
#property (weak, nonatomic) IBOutlet UITabBar *tabBar;
#end
FirstViewController.m
#import "FirstViewController.h"
#import "SWRevealViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
SWRevealViewController *revealController = [self revealViewController];
[self.view addGestureRecognizer:revealController.panGestureRecognizer];
UIBarButtonItem* revealButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"reveal-icon.png"] style:UIBarButtonItemStylePlain target:revealController action:#selector(revealToggle:)];
self.navigationItem.leftBarButtonItem = revealButtonItem;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
NSUInteger indexOfTab = [[tabBar items] indexOfObject:item];
NSLog(#"Tab index = %u", (int)indexOfTab);
if(indexOfTab == 0){
[[NSNotificationCenter defaultCenter] postNotificationName:#"backToTabIndexControllerFirst" object:nil];
}else{
[[NSNotificationCenter defaultCenter] postNotificationName:#"backToTabIndexControllerSecond" object:nil];
}
}
The notifications fired from here will change the root controller of the application.
Similarly we will code for SecondViewController
Assuming that there is a Table For selection of various other controllers from LeftSidePanel, we will add the tableView's didSelectRowAtIndexPath method as follows:
LeftSideViewController.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SWRevealViewController *revealController = self.revealViewController;
[revealController revealToggleAnimated:YES];
// Used this just to show the animation completion and then changing the root
[self performSelector:#selector(changeControllers:) withObject:indexPath afterDelay:0.3];
}
-(void)changeControllers:(NSIndexPath*)indexPath{
if(indexPath.row == 0){
[[NSNotificationCenter defaultCenter] postNotificationName:#"firstVCWithoutNAV" object:nil];
}else{
[[NSNotificationCenter defaultCenter] postNotificationName:#"secondVCWithoutNAV" object:nil];
}
}
We can also use other libraries as I already stated for side panel. Example
https://github.com/mikefrederick/MFSideMenu
Hope this solves the problem!
I know this question has been asked before here iOS 6 shouldAutorotate: is NOT being called. But my scenario is a bit different.
Initially, on application launch I load a viewController like
self.window.rootViewController = self.viewController;
and When this view is loaded I am using a custom tabBar view (inherited from UIView) which has 5 UINavigationController for each tab. The code of this viewController Class is:
\\\ .h File
#protocol tabbarDelegate <NSObject>
-(void)touchBtnAtIndex:(NSInteger)index;
#end
#class tabbarView;
#interface ViewController : UIViewController <tabbarDelegate>
#property(nonatomic,strong) tabbarView *tabbar;
#property(nonatomic,strong) NSArray *arrayViewcontrollers;
#property(nonatomic,strong) UINavigationController * navigation1;
#property(nonatomic,strong) UINavigationController * navigation2;
#property(nonatomic,strong) UINavigationController * navigation3;
#property(nonatomic,strong) UINavigationController * navigation4;
#property(nonatomic,strong) UINavigationController * navigation5;
#end
and m file is
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat orginHeight = self.view.frame.size.height- 60;
_tabbar = [[tabbarView alloc]initWithFrame:CGRectMake(0, orginHeight, 320, 60)];
_tabbar.delegate = self;
[self.view addSubview:_tabbar];
_arrayViewcontrollers = [self getViewcontrollers];
[self touchBtnAtIndex:0];
}
-(void)touchBtnAtIndex:(NSInteger)index \\This delegate method is called on every custom tabBar button clicked.
{
UIView* currentView = [self.view viewWithTag:SELECTED_VIEW_CONTROLLER_TAG];
[currentView removeFromSuperview];
UINavigationController *viewController = [_arrayViewcontrollers objectAtIndex:index];
viewController.view.tag = SELECTED_VIEW_CONTROLLER_TAG;
viewController.view.frame = CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height- 50);
[self.view insertSubview:viewController.view belowSubview:_tabbar];
}
-(NSArray *)getViewcontrollers
{
FirstViewController *firstController = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *secondController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
ThirdViewController *thirdController = [[ThirdViewController alloc]initWithNibName:#"ThirdViewController" bundle:nil];
ForthViewController *forthController = [[ForthViewController alloc]initWithNibName:#"ForthViewController" bundle:nil];
FifthViewController *fifthController = [[FifthViewController alloc]initWithNibName:#"FifthViewController" bundle:nil];
navigation1 = [[UINavigationController alloc] initWithRootViewController:firstController];
navigation2 = [[UINavigationController alloc] initWithRootViewController:secondController];
navigation3 = [[UINavigationController alloc] initWithRootViewController:thirdController];
navigation4 = [[UINavigationController alloc] initWithRootViewController:forthController];
navigation5 = [[UINavigationController alloc] initWithRootViewController:fifthController];
NSArray* tabBarItems = [[NSArray alloc] initWithObjects:navigation1,navigation2,navigation3,navigation4,navigation5, nil];
return tabBarItems;
}
I have also implemented UINavigationController's category for rotation as:
#implementation UINavigationController (autoRotation)
-(BOOL)shouldAutorotate {
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
My Problem is that only supportedInterfaceOrientations method is called and shouldAutorotate is never called. The main Window's rootViewController is ViewController class, not any UINavigationController or UITabBarController. What I am doing wrong? Please help me.
If you add these to your root view controller:
- (BOOL)shouldAutorotate
{
NSLog(#"ViewController shouldAutorotate super=%d", [super shouldAutorotate]);
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
NSLog(#"ViewController supportedInterfaceOrientations");
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
you will see that the system is constantly sending both of these messages. Your code there can query the active Navigation Controller to see what values to return if you wish.
Also, I'm no fan of using a category to override these on a UINavigation Controller - that it works is somewhat of a fluke and importing some other library that does the same could cause unexpected consequences later on. Just create a really simple subclass and over ride both of these. I've been doing that with both UITabBarController and UINavigationController since iOS4 and never had an issue.
As I mentioned in the title, I want to add Navigation Controller to my application which already has a Tab Controller. So trying to do the staff something like on this page. Anyway, something is wrong. UINavigationController is looking a blank page, even if has a view and some libraries.
Let me begin from the stracht:
In my AppDelegate, I'm setting tab bar controllers like this:
#interface MYAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UITabBarController *tabBarController;
#end
And here is .m file:
#implementation MYAppDelegate
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
application.applicationSupportsShakeToEdit = YES;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *viewController1 = [[[MYMainViewController alloc] init] initWithNibName: #"MYMainViewController" bundle:nil];
UIViewController *viewController2 = [[[MYPageViewController alloc] init] initWithNibName:#"MYPageViewController" bundle:nil];
UIViewController *viewController3 = [[[MYSearchViewController alloc] init] initWithNibName:#"MYSearchViewController" bundle:nil];
UIViewController *viewController4 = [[[MYPersonViewController alloc] init] initWithNibName:#"MYPersonViewController" bundle:nil];
// Initialize tabBarController and add ViewControllers
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects: viewController1, viewController2,
viewController3, viewController4, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Then, here is MYMainViewController implementaion which is a UINavigationController:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", [self navigationController]); // Logging null
}
My .xib file has a UINavigationController and and there is a view in it. Althought it, when I worked the app, there is blank page and untitled navigation bar. What am I doing wrong?
If I could see the content of my view, I want to navigate between two view controllers by using back button.
Any help or approach would be great for me.
Try to remove navigation controller from xib, so it only have view controller, then initialize navigation controller programatically:
UIViewController *tmpViewController1 = [[[YourViewController alloc] init] initWithNibName:#"YourViewController" bundle:nil];
UINavigationController *viewController1 = [[UINavigationController alloc] initWithRootViewController:tmpViewController1];
I've got an app where I am pushing a modal view controller. It is working fine, but I am concerned I haven't coded it in the most correct fashion. I have instanstiated two navigation controllers, which seems a bit dodgy to me.
Basically I've created a tab bar controller with 3 tabs, then made one of those tabs / view controllers the root. Later I am (using some home-grown markup on core text) popping a view controller when the user touches a particular word in a paragraph. The pushed view controller has a back button which works fine and the app seems to be OK.
Like I said it all works, but it seems I am coding in circles here. Is this correct?
AppDelegate.h
#import <Foundation/Foundation.h>
#interface AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
{
UIWindow *window;
UITabBarController *tabBarController;
}
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UITabBarController *tabBarController;
#end
From AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
ViewController2 *viewController2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
ViewController3 *viewController3 = [[ViewController3 alloc] initWithNibName:#"ViewController3" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:nav, viewController2, viewController3, nil];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
ViewController3.h
#import <UIKit/UIKit.h>
#import "JSCoreTextView.h"
#import "PopupViewController.h"
#class JSTwitterCoreTextView;
#interface ReadingViewController : UIViewController <JSCoreTextViewDelegate>
{
JSTwitterCoreTextView *_textView;
UIScrollView *_scrollView;
}
#end
From ViewController3.m
Here I am instantiating another navigation controller. Is this a good idea?
- (void)textView:(JSCoreTextView *)textView linkTapped:(AHMarkedHyperlink *)link
{
PopupViewController *popupVC = [[PopupViewController alloc] initWithNibName:#"PopupViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:popupVC];
[nav setModalPresentationStyle:UIModalPresentationFullScreen];
[nav setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentModalViewController:nav animated:YES];
}
From PopupViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(done:)]];
}
- (void)done:(id)sender
{
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
It appears the answer is "yes". I was under the impression there is a single Navigation Controller for the app, but it's more like one per tab, depending on if there are going to be further pushes from that tab.