Using XCode 4.5 & iOS6
I created a UINavigationController with a UITabBar (NIBs) and the tab vertical positioning for the first launch is incorrect. When you click the second tab and again the first tab the vertical positioning is OK.
So ... How can I have the first tab properly positioned when the first run is done?
See wrong positioning:
http://img231.imageshack.us/img231/2159/badbf.png
My code:
AppDelegate.h
#interface bib_AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UINavigationController *mainControllercode;
#property (strong, nonatomic) UITabBarController *tabBarController;
in the AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// change defaul selected icon tabbar color to orange
[[UITabBar appearance] setSelectedImageTintColor:[UIColor orangeColor]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[agendaViewController alloc] initWithNibName:#"agendaViewController" bundle:nil];
UIViewController *viewController2 = [[messagesViewController alloc] initWithNibName:#"messagesViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[viewController1, viewController2];
self.mainControllercode = [[UINavigationController alloc] initWithRootViewController:self.tabBarController];
self.window.rootViewController = self.mainControllercode;
[self.window makeKeyAndVisible];
return YES;
}
agendaViewController.h
#import <UIKit/UIKit.h>
#interface agendaViewController : UIViewController
#end
agendaViewController.m
#import "agendaViewController.h"
#interface agendaViewController ()
#end
#implementation agendaViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Agenda", #"Agenda");
self.tabBarItem.image = [UIImage imageNamed:#"83-calendar"];
}
return self;
}
- (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
EDIT 1:
I created a sample project with Storyboards that you can see. I would like to have the same features without Storyboards, download this here:
http://www.freefilehosting.net/atestsb
Thanks
You are going about this the wrong way.
A UITabBarController should have a collection of UINavigationControllers which then have their root controller set to the primary Nib. Each tab then handles its own navigation stack.
You are currently putting the UITabBarController inside the root of the UINavigationController. This will cause issues as well as remove the tab bar when you move through the navigation stack.
Check out this link for more details to handle it programmatically :
http://www.xdracco.net/howto-implement-uinavigationcontroller-uitabbarcontroller-programmatically/
Related
May somebody let me know:
How to navigate from one view to another view in single viewcontroller in iphone sdk? I have an application in which i want to push to next view and pop to previous view in a single View controller. How this functionality can be achieved?
Thanks in advance
You can add and remove your secondview.Like this to navigate
-(IBAction)navigate:(id)sender
{
[self.view addSubView:secondView];
}
and this one to po to first view
-(IBAction)popToFirstView:(id)sender
{
[secondView removeFromSuperView];
}
Note:- You can use animations for adding and removing view, if you want to give animated effects.
If you need a single view controller you can try using a UIScrollView, that contain the 2 view, and a button to scroll from a view to another... but if i can give a tip, it's better using 2 view controller and a navigation view controller
You need to use UINavigation Controller to get push and pop.
do this way
In AppDelegate.h file
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
//this will be your first screen
#property (strong, nonatomic) FavViewController *favViewController;
#end
In A*ppDelegate.m* file
#import "AppDelegate.h"
#import "FavViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize favViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//initialize view controller
favViewController = [[FavViewController alloc] initWithNibName:#"FavViewController" bundle:nil];
//add navigation controller
UINavigationController *favouriteView = [[UINavigationController alloc] initWithRootViewController:favViewController];
//add controller to witndow
self.window.rootViewController = favouriteView;
[self.window makeKeyAndVisible];
return YES;
}
#end
Now come to the UIViewController, where you want to load/push to new controller
to load/push to new controller use this code
//this will be next screen
DetailsViewController *detailsViewController = [[DetailsViewController alloc ]init];
[self.navigationController pushViewController:detailsViewController animated:YES];
to go back or pop controller use this
//now it will send back to parent screen
[self.navigationController popViewControllerAnimated:YES];
I have figured out the solution for this problem and here is the solution as below:-
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UIButton *backbtn;
IBOutlet UIButton *nxtBtn;
IBOutlet UILabel *label;
}
-(IBAction)nxt:(id)sender;
-(IBAction)ba:(id)sender;
#end
#import "ViewController.h"
#interface ViewController ()
#end
int count=0;
#implementation ViewController
- (void)viewDidLoad
{
label.text=[[NSUserDefaults standardUserDefaults] objectForKey:#"NavigtionNumber"];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
-(IBAction)nxt:(id)sender
{
count++;
label.text=[NSString stringWithFormat:#" navigation time %d",count];
[[NSUserDefaults standardUserDefaults] setObject:label.text forKey:#"NavigtionNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
ViewController *vc=[[ViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
-(IBAction)ba:(id)sender
{
count--;
label.text=[NSString stringWithFormat:#" navigation time %d",count];
[[NSUserDefaults standardUserDefaults] setObject:label.text forKey:#"NavigtionNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.navigationController popViewControllerAnimated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Hope this will help others in future.
Thanks.
I'm diving into iOS development and I'm trying to create an iPad app that uses the split view layout, without using the UISplitViewController. I found this question already posted, but it's too vague to help me with my current level of iOS experience.
In short, I have a UIViewController class named MySplitViewController that contains two children view controllers, one for the master view and one for the detail view. I'm trying to implement this in a way that when I push an instance of MySplitViewController onto the nav stack, I get a table view (master) on the left and a detail view on the left. However, when I run my code, the entire split view is filled with the table view. How can I manually create a Split View layout? Here are my three view controller classes, they're very simple...
MySplitViewController.m
#import "MySplitViewController.h"
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MYSplitViewController (){}
#property (nonatomic, strong) MasterViewController *masterViewController;
#property (nonatomic, strong) DetailViewController *detailViewController;
#end
#implementation MySplitViewController
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
self.masterViewController = [[MasterViewController alloc] initWithNibName:nil bundle:nil];
self.detailViewController = [[DetailViewController alloc] initWithNibName:nil bundle:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.frame = CGRectMake(0, 0, 768, 1004);
[self.view addSubview:self.masterViewController.view];
[self.masterViewController viewDidLoad];
[self.view addSubview:self.detailViewController.view];
[self.detailViewController viewDidLoad];
}
#end
MasterViewController.m
#import "MasterViewController.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 100, 1004) style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.view addSubview:table];
}
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
UIView *uiview = [[UIView alloc] initWithFrame:CGRectMake(100, 0, 668, 1004)];
[self.view addSubview:uiview];
}
#end
What am I not understanding?
Thanks so much in advance for your wisdom!
P.S. It's worth noting why I'm not using the UISplitViewController. My app is currently designed so that the root view is not split view. The root view of my app will cause a split view to be pushed on to the nav stack. The problem with this is that the UISplitViewController is designed to be the root view of an app and Apple's docs specifically say that if you use a UISplitViewController that it needs to be the root view. Therefor, I'm implementing my own split view and manually managing the views.
Maybe thinking about showing your root view in a different way could help you. e.g like this: using a UISplitViewController as root view and present a modal view on top of it with your current root view. So you use your current root view and the UISplitViewController.
you might wanna try MGSplitViewController which is also based on UIViewController.. and allows push..MGSplitViewController
I am very new to iOS development and would appreciate if experts here would be able to help me with my problem. At the moment, my application is extremely basic and does nothing much. Prior to trying to add a tab bar to my existing view, things worked fine. I am not sure what I'm missing but nothing is showing when I run the simulation. I'll try my best to explain the structure of my application so that you guys can understand the problem better.
The following are currently present in the application...
FeedList: A UITableViewController embedded inside a UINavigationController.
FeedCell: A UITableViewCell created for FeedList.
FeedItemDetail: A UIViewController with a UIScrollView within it. User will be brought to this screen by tapping on a cell in FeedList.
Below are the codes for AppDelegate.h and AppDelegate.m. I would greatly appreciate it if someone is able to tell me why nothing is showing on my simulation screen. Thanks!
//AppDelegate.h
#import <UIKit/UIKit.h>
#import "FeedList.h"
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
FeedList *feedList;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) FeedList *feedList;
#property (nonatomic, retain) UITabBarController *tabBarController;
- (void)customizeAppearance;
#end
//AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window, feedList, tabBarController;
// Entry point
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
tabBarController = [[UITabBarController alloc] init];
feedList = [[FeedList alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:feedList];
tabBarController.viewControllers = [NSArray arrayWithObject:nav];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
Update (problem solved)
I realized that after adding the line tabBarController.viewControllers = [NSArray arrayWithObject:nav]; things start to go haywire. After checking Apple's Documentation, the reason is because if the value of this property is changed at runtime, the tab bar controller removes all of the old view controllers before installing the new ones. It is therefore required that we set the new tab bar controller as the root view controller.
I agree with Dustin's comment, you should use the storyboard if you are starting off new. What I see wrong with your method, or different from typical anyway, is that you don't add tabBarController as subview you set the rootViewController of self.window like so:
// Entry point
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
tabBarController = [[UITabBarController alloc] init];
feedList = [[FeedList alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:feedList];
tabBarController.viewControllers = [NSArray arrayWithObject:nav];
//******* This is my correction *******
window.rootViewController = tabBarController;
//******* *******
[window makeKeyAndVisible];
}
Of course there is no way to tell from the info you provided if your tableview is set up right so there is no guarantee this will display your table.
I have the following code in my AppDelegate:
#import <UIKit/UIKit.h>
#class PersonalDiarySystemViewController;
#interface PersonalDiarySystemAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
PersonalDiarySystemViewController *viewController;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet PersonalDiarySystemViewController *viewController;
#property (nonatomic, retain) UINavigationController *navigationController;
#end
#import "PersonalDiarySystemAppDelegate.h"
#import "PersonalDiarySystemViewController.h"
#implementation PersonalDiarySystemAppDelegate
#synthesize window;
#synthesize viewController;
#synthesize navigationController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the view controller as the window's root view controller and display.
self.window.rootViewController = self.viewController;
navigationController = [[UINavigationController alloc] initWithRootViewController:self.window.rootViewController];
navigationController.navigationBar.tintColor = [UIColor
colorWithRed:217.0/255
green:33.0/255
blue:0
alpha:1];
navigationController.navigationBarHidden = YES;
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
My rootviewcontroller tries to load another viewcontroller into the navigation controllers stack in its viewDidLoad method but for some reason the view is not getting pushed:
-(void) viewDidLoad{
lvc = [[LoginViewController alloc] init];
//lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[lvc setDelegate:self];
//[self presentModalViewController:lvc animated:YES];
[self.navigationController pushViewController:lvc animated:YES];
}
I'm getting no errors so not sure whats going on...using presentModalViewController works...so really am confused!!
You need to assign lvc to LoginViewController.
- (void) viewDidAppear
{
[self performSelector:#selector(loginCheck:) withObject:nil afterDelay:0.5];
}
- (void) loginCheck:(id)sender
{
LoginViewController * lvc = [[LoginViewController alloc] init];
//lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[lvc setDelegate:self];
//[self presentModalViewController:lvc animated:YES];
[self.navigationController pushViewController:lvc animated:YES];
}
Put your
[self.navigationController pushViewController:loginViewController];
Into the
- (void)viewDidAppear:(BOOL)animated
method. The viewControllers navigationController doesn't get loaded until then
There are two things that might go wrong.
First, you alloc the navigation controller in applicationDidFinishLaunching, I'm not quite sure which goes first, applicationDidFinishLaunching or viewDidLoad.
As you've seen, you first set your root view controller, then alloc the navigation controller, then maybe viewDidLoad launched right after you set the root view controller, then the navigation controller is allocated. so the words in viewDidLoad may not work because at that time, the navigation controller hasn't been born yet.
But I don't' quite thing the previous explanation works. it's just a possibility.
There's another strange thing, you set the navigation bar of your navigation controller hidden
navigationController.navigationBarHidden = YES;
Then it seems that the user can't pop back to the root view controller, so the navigation controller don't push the login view controller.
Meanwhile, the modal view controller can be dismissed with the navigation bar hidden or the navigation bar not allocated, so it works when you present it as a modal view controller.
but i'm still not quite sure about it since i'm now having some issues with Xcode, so i can't test the previous two ideas, sorry about that. but i still recommend that you set navigationBarHidden to NO.
- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.navController = navigationController;
[mainViewController release];
[navigationController release];
// Configure and display the window.
[window addSubview:navController.view];
[window makeKeyAndVisible];
}
- (void)viewDidLoad{
lvc = [[LoginViewController alloc] init];
[self.navigationController pushViewController:lvc animated:YES];
}
I'm a beginner with Xcode and Objective-C, i want to make a view controller in code without a nib file and shape it how i want. Currently with this very simple code I can't seem to even change the background color because of EXC_BAD_ACCESS.
I read on internet it is something with memory management but I can't seem to find the fix for this. Pieces of my code:
AppDelegate.h
#import <UIKit/UIKit.h>
#import "DefaultViewController.h"
#class DefaultViewController;
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UIViewController *rootViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UIViewController *rootViewController;
#end
AppDelegate.m
#synthesize window = _window;
#synthesize rootViewController = _rootViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController *rvc = [[DefaultViewController alloc] init];
self.rootViewController = rvc;
[rvc release];
[self.window addSubview:self.rootViewController.view];
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[_window release];
[_rootViewController release];
[super dealloc];
}
The view controller I made via, right click -> new file and UIViewController subclass without xib! In the loadView I only try this:
self.view.backgroundColor = [UIColor redColor];
The problem could be that the rootViewController doesn't have an initialized view. Hard to tell, since you don't show the code of the DefaultViewController. It could also be another error in DefaultViewController.
FWIW, you have two obsolete ivars:
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UIViewController *rootViewController;
}
You can delete these, since you synthesize _window and _rootViewController and never use the above.
There are a few issues with your code. But first the key problem you are getting EXC_BAD_ACCESS is because you are calling self.view.backgroundColor inside the loadView. If you override loadView, you must construct your view hierarchy inside the method. By not creating a view hierarchy in that method you are calling backgroundColor on a view that does not exist. Instead completely remove the loadView method or comment it out and move self.view.backgroundColor into the viewDidLoad method. (Remember even an empty loadView method will be a problem, you need to remove it or comment it out)
Second.. change your code to
self.rootViewController = rvc; to self.window.rootViewController = rvc;
BTW, once you add a view controller you don't need to add the view of the rootViewController as a subview to the window again. Assigning a view controller to the rootViewController property installs the view controller's view as the content view of the window.
Third. When you are initializing DefaultViewController you do
UIViewController *rvc = [[DefaultViewController alloc] init];
dont do that, instead do
DefaultViewController *rvc = [[DefaultViewController alloc] init];
Change the code so it's
self.window.rootViewController = rvc;
[self.window makeKeyAndVisible];
return YES;
What's inside your DefaultViewController? If you are not using a nib file, did you implement -(void)loadView ?
You should call:
UIViewController *rvc = [[DefaultViewController alloc]
initWithNibName:#"yournib" bundle:nil];
to load the NIB view. Otherwise, your rvc.view will be nil.
Sorry, I overlooked.
The answer is: you should not call self.view.backgroundColor = [UIColor redColor]; within - (void)loadView since self.view is nil firstly at this stage. He has to show that he has correctly created at least self.view = [[UIView alloc] init] in loadView.