I have an application which has a view called store. In this view there is a button which loads the DetailView. Problem is that this detailview doesn't load/show. This is the code I use:
-(void)knop:(id)sender{
categoryView = [[CategoryView alloc] init];
//show detail view using buttonDetail...
[self.navigationController pushViewController:categoryView animated:YES];
[categoryView release];
NSLog(#"Button is working");
}
The log "Button is working" logs, so the pushViewController line is also triggered.
categoryView is made in my .h file:
CategoryView IBOutlet *categoryView;
}
#property (nonatomic, retain) IBOutlet CategoryView *categoryView;
In the store.xib there is a UIViewController with an outlet linked to the categoryView outlet.
Somewhere else in my app this is working, and I can't seem to find out why this one isn't
Any help would be appreciated!
THNX
Did you assign the UINavigationController in your AppDelegate?
#interface
#property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#implementation didFinishLaunchingWithOptions
rootViewController = [[RootViewController alloc] initWithNibName:#"RootView" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
[window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
pushViewController works fine then through the whole App.
It sounds like
NSLog(#"nav controller = %#", self.navigationController);
will show that navigationController is nil.
I suggest creating a new project of navigation type and see how this should be setup.
I have found it. Since I was using a tabbar based app, I needed to change the store tab to Navigation Controller. When I changed it, it worked! Thanks for all your support!!!
If your view is nib based, you need to use:
categoryView = [[CategoryView alloc] initWithNibName:nibName bundle:nibBundle];
Hope this helps.
Related
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 mainWindow.xib in my application with a TabController in it for my main-menu.
Now I want to have a Login-form for my application.
I added a View (LoginViewController) and show this view at beginning:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the tab bar controller's current view as a subview of the window
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
LoginViewController *lvc = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
lvc.delegate = self;
[self.tabBarController presentModalViewController:lvc animated:false];
[lvc release];
return YES;
}
Next I have my login-checks in the view, okay.
Now I try to dismiss the view after this.
For this I searched around and found the question here: present modal view controller
I add all things to my project, but getting a error in this code:
#import <UIKit/UIKit.h>
#interface Animexx3AppDelegate : NSObject <UIApplicationDelegate,
UITabBarControllerDelegate, LoginViewControllerDelegate>
{
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Which means "cannot find protocol LoginViewControllerDelegate" in line 2/3.
Addition in the line "lvc.delegate = self" I get a warning that tells me "assigning to "id" from incompatible type "Animexx3AppDalagte".
What did Im wrong?
You need to import the header file where you declared the LoginViewControllerDelegate protocol. Most likely the LoginViewController.h file.
After struggling with this many times, we published an open source library called CLHoppingViewController which handles exactly this kind of scenarios.
So, in your case, you would do something like this to describe the start up flow:
UIViewController *loginViewController;
UIViewController *mainViewController;
if (user_not_logged_in) {
[self hopToViewController:loginViewController then:^{
[self hopToViewController:mainViewController then:nil];
}];
}
else {
[self hopToViewController:mainViewController then:nil];
}
The library can support much more advanced conditional sequences. For example, you can display a splash screen, conditionally show onboarding UX, etc.
There's a short tutorial here.
I have an iPhone project that starts out with a standard UIView based Window... when the user clicks a button its suppose to launch into a new view with a UITabBarController -- similar to the way the iTunes Connect app behaves after you login. There are no sample code examples in the Apple documentation doing what I want but I know its possible because Apple has done it in their own apps (another example is the MobileMe iDisk app for iPhone).
I already tried the standard -presentModalViewController:animated: method and that did not work because there isn't a view that I can attach within the UITabBarController.
Next I am going to attempt to work with two window XIBs within the App Delegate to see if I can get that approach to work instead.
I would appreciate any insight if you know how to answer this little problem of mine. =)
What I ended up doing is this:
In my App Delegate, I have the following in my interface:
#interface myAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow * window;
LauncherViewController * startup;
UITabBarController * tabs;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet LauncherViewController * startup;
#property (nonatomic, retain) IBOutlet UITabBarController * tabs;
#end
In my implementation file, I add the following to the app start up function:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self.window addSubview:self.startup.view];
[self.window makeKeyAndVisible];
NSNotificationCenter * notifier = [NSNotificationCenter defaultCenter];
[notifier addObserver:self
selector:#selector(launch)
name:MyAppLoginInitializedNotification
object:nil];
[notifier addObserver:self
selector:#selector(logout)
name:MyAppLogoutNotification
object:nil];
return YES;
}
- (void) launch {
[self.startup.view removeFromSuperview];
[self.window addSubview:tabs.view];
[self.window makeKeyWindow];
}
- (void) logout {
[self.tabs.view removeFromSuperview];
[self.window addSubview:startup.view];
[self.window makeKeyWindow];
}
My main XIB contains both the standard UIViewController defined as LauncherViewController as well as a generic UITabBarController. As soon as my main launcher controller authentices the user credentials and sends the MyAppLoginInitializedNotification, the app delegate switches from the launcher to the tab view enabling me to continue on with my app logic.
UITabBarController really is just a subclass of UIViewController, so -presentModalViewController:animated: should work:
UITabBarController *someController = [[UITabBarController alloc] init];
someController.viewControllers = /* your View Controllers here */
[self presentModalViewController:someController animated:NO];
if i understand your issue correctly, you want to start the UITabBarController View after the first view you mentioned in your Question, i am attaching a link doing the same thing you need except you have an Extra view before the UITabBarController View appears, hope it will give you a guide.
http://www.mobisoftinfotech.com/blog/iphone/iphone-tabbar-uitabbarcontroller-tutorial/
I don't think you have to re-add the UITabBarController in the nib file. Just create it in code, add it as the poster above says, and you should be good to go. Here's some code that works for me.
UITabBarController *nextController = [[UITabBarController alloc] init];
FirstController *firstView = [[FirstController alloc] initWithNibName:#"FirstView" bundle:nil];
SecondController *secondView = [[SecondController alloc] initWithNibName:#"SecondView" bundle:nil];
ThirdController *thirdView = [[ThirdController alloc] initWithNibName:#"ThirdView" bundle:nil];
[nextController setViewControllers:[NSArray arrayWithObjects:firstView, secondView, thirdView, nil] animated:NO];
Till this point it should be the same, but I'm pushing a tabbar controller into the uinavgiationcontroller instead, so this is where we might differ. I do it as follows:
[self.navigationController pushViewController:nextController animated:YES];
I'm attempting to switch views with an iPhone application- I have a parent view controller, SuperviewController, and then two views that I want to switch within that parent view, MainMenuController and MainGameController.
*EDIT*: I am now using navigation controllers:
SuperviewController.m
viewDidLoad
self.mainMenuController = [[MainMenuController alloc] initWithNibName:#"MainMenu" bundle:nil];
[[self navigationController] pushViewController:self.mainMenuController animated:NO];
switchToMainGame
self.mainGameController = [[MainGameController alloc] initWithNibName:#"MainGame" bundle:nil];
[[self navigationController] pushViewController:self.mainGameController animated:NO];
The app loads correctly with the mainMenu.xib. However, when calling switchToMainGame, nothing happens- it's as if XCode forgot what mainGameController is.
Thanks for any help.
You might consider swapping view controllers not views, using UINavigationController.
In your AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
And in -[AppDelegate applicationDidFinishLaunching:] instantiate navigationController, thus:
[self setNavigationController:[[UINavigationController alloc] initWithRootViewController:mySuperviewController]];
[[self navigationController] setNavigationBarHidden:YES];
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
Then within SuperviewController.m you can instantiate your MainMenuController and MainGameController, as you already do. To start with MainMenuController you could do this in SuperviewController -viewDidLoad
[[self navigationController] pushViewController:[self mainMenuController] animated:YES];
You would need to add some smarts to switch directly between mainMenuController and mainGameController - but it wouldn't be difficult.
So as not to reload nibs again and again, consider defining accessor methods like this:
- (MainGameController*) mainGameController
{
if (mainGameController == nil)
{
mainGameController = [[MainGameController alloc] initWithNibName:#"MainGame" bundle:nil];
}
return mainGameController;
}
Also, bear in mind that switching between sibling view controllers involve popping current view controller (e.g., mainMenuController) before pushing other view controller (e.g., mainGameController).
I have a TabBar application with several nibs, most with a NavBar. It works pretty well, except for the "views" that are inside the "More" section of the tabBar.
As expected, it will put a NavBar to return to the "More" list, as well as the NavBar i've placed in the nib.
I've tried to remove the view controllers from the moreNavigationBar and put the top controller from my nib's navBar, but I get and extra view from somewhere:
- (void)viewDidLoad {
TestAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
UITabBarController *ctrl = appDelegate.rootController;
UINavigationController *navCtrl = ctrl.moreNavigationController;
[navCtrl popToRootViewControllerAnimated: NO];
[navCtrl pushViewController: navController.topViewController animated: YES];
navController = navCtrl;
[super viewDidLoad];
}
My AppDelegate:
#interface TestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *rootController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
The MainWindow nib is that of a Window-based project with a TabBarController, linked to the rootController in my app delegate.
The other nibs have a view + navigationController and I have a UITableViewController subclass as my Root View Controller.
If I could get this to work it wouldn't still solve my problem, because I want to allow the user to place this anywhere in the tabBar, so, I must have some way of knowing if there's a navigationBar.
So, my question is, how do you know if there's a navigationBar (in this case, if the tabBar's navigationBar is being shown) and, if so, how do I get my navigationController to "become" the tabBar's navigationController?
Or, if you have another idea on how to solve this problem, i'd also be appreciated :)
The recommendation from apple is that you have the TabBar controller contain the Navigation controllers and not the other way around. I have a setup more or less like this, and I have the More tab hold a Nav controller, basically like this:
#interface SomethingNavViewController : UIViewController {
UIView* aview;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIView *aview;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
In the NIB, I have a separate Nav controller in the view of the more panel, I haven't replaced the tab bar item's view with a nav controller view, I've just added a Nav controller to the view.
In my implementation file, I have:
- (void)viewDidLoad {
[super viewDidLoad];
[[self view] addSubview:[navigationController view]];
SomeOtherController *aController = [[[SomeOtherController alloc ] initWithNibName:#"SomeOtherController" bundle:nil ] autorelease];
aController.title = #"Artwalks";
// lots of application logic here.
[self.navigationController pushViewController:aController animated:YES];
[self.navigationController setDelegate:self];
}
One key thing about this is that I have implemented the navigationController's delegate method, which is really handy when you're just inserting the nav controller. I found when I didn't do this, my views don't get viewDidAppear messages, so I implemented the protocol and added this method:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([viewController respondsToSelector:#selector(viewDidAppear:)]) {
[viewController viewDidAppear:animated];
}
}
and that solved a variety of my lingering problems.
Anyway, I hope this answer gave you the detail you needed. IF it didn't, please give more details about your question. I'm not quite sure what but I get and extra view from somewhere met, but it sounds like something I encountered before I found this solution.