SimpleDrillDown example with TabBarController - ios

I have been experimenting with the SimpleDrillDown example from Apple and attempted to put it into a tab bar. The problem is the view now doesn't show, and I know it is the following code in the App Delegate that is causing it. I am struggling with changing it to fit with the tabbar and would appreciate some pointers.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Create the data controller and pass it to the root view controller.
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
RootViewController *rootViewController = (RootViewController *)[[navigationController viewControllers]objectAtIndex:0];
DataController *controller = [[DataController alloc] init];
rootViewController.dataController = controller;
self.dataController = controller;
}
I have replaced it with the following but this line EatCatTVC *rootViewController = (RootViewController *)[[navigationController viewControllers]objectAtIndex:0]; throws an error
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UITabBarController *tabBar = (UITabBarController *)self.window.rootViewController;
// Create the data controller and pass it to the root view controller.
EatCatTVC *rootViewController = (RootViewController *)[[navigationController viewControllers]objectAtIndex:0];
DataController *controller = [[DataController alloc] init];
rootViewController.dataController = controller;
self.dataController = controller;
return YES;
}

Your code is failing because you are accessing non-existent object
EatCatTVC *rootViewController = (RootViewController *)[[navigationController viewControllers]objectAtIndex:0];
on this line navigationController doesn't exist in your "modified" version.
Make sure that "rootController" is set to UITabBarController class (I assume that you did setup this in Interface Builder).
And then use setViewControllers:animated: to provide the UITabBarController' instance with (for instance)UIViewController` instances that are meant to be present.

Related

Set rootViewController inside a class of UINavigationController

I have a UINavigationController in my storyboard and two viewControllers which perform the following function:
InitialViewController: this would be the application's home screen.
FirstTimeViewController: is the screen that appears when the user open
the app for the first time.
My UINavigationController has a class that have the following code:
- (void)viewDidLoad {
[super viewDidLoad];
if ([[ReadPlist initWithPlist:#"Configuration.plist" key:#"initialConfiguration"] boolValue]){
FirstTimeViewController *firstTimeController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"firstTimeView"]; //or the homeController
[self.navigationController pushViewController:firstTimeController animated:NO];
}else{
InitialViewController *initialController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"initialView"]; //or the homeController
[self.navigationController pushViewController:initialController animated:NO];
}
}
Basically this code verify the .plist file if a particular field is active, if YES means that the application is running for the first time, in this case it calls the corresponding viewController.
But this code is not working and I see a NavigationController with a black view. All I would do is the same thing we do in the interface builder, simply drag a line from the UINavigationController inside a UIViewController and set as "Root View Controller", but in my case I'm trying to do this programmatically.
How I can do this?
When you push to FirstTimeViewController Set Bool (User Default) in controller ViewDidload Or in your Success Code.then after set in your AppDelegate below code.
if(Bool value = Yes)
{
FirstTimeViewController *FS=[[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"FirstTimeViewController"];
UINavigationController *navController=[[UINavigationController alloc]initWithRootViewController:FS];
[navController setNavigationBarHidden:YES];
self.window.rootViewController=navController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
}
My answer is
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)options
{
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
FirstTimeViewController *firstTimeVC = [navController.storyboard instantiateViewControllerWithIdentifier:#" FirstTimeViewController"];
InitialViewController *initialVC = [navController.storyboard instantiateViewControllerWithIdentifier:#" InitialViewController"];
if ([[ReadPlist initWithPlist:#"Configuration.plist" key:#"initialConfiguration"] boolValue])
{
// FirstTime
navController.viewControllers = [NSArray arrayWithObject:firstTimeVC];
}
else
{
// Initial
navController.viewControllers = [NSArray arrayWithObject:initialVC];
}
[self.window makeKeyAndVisible];
return YES;
}

Setting UINavigationController (from storyboard) as rootViewController in AppDelegate.m

I'm using parse and I'm trying to get the login screen to show if the user isn't the "current" user. I'm having issues with my NavigationController (from my storyboard) and using it as the rootViewController even though it's already set as initial View Controller in my storyboard. Using this line of code I select the NavigationController (from my storyboard) and initialize it in my app delegate.
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
I then decide whether or not to display the loginVC then finally I set the NavigationController as the rootViewController here:
self.window.rootViewController = navVC; [self.window makeKeyAndVisible];
Except someone I don't. I get this error when I try to build my app. "Application windows are expected to have a root view controller at the end of application launch" Anyone have any ideas what's going wrong?
Here's the code all together.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
// Initialize Parse.
[User registerSubclass];
[Question registerSubclass];
[Parse setApplicationId:#"HI"
clientKey:#"HI"];
// Determine whether or not to show the login screen
if (![PFUser currentUser]) {
LogInViewController *loginVC = [[LogInViewController alloc] init];
[navVC setViewControllers:#[loginVC] animated:YES];
} else {
QuestionsTableViewController *questionsVC = [[QuestionsTableViewController alloc] init];
[navVC setViewControllers:#[questionsVC] animated:YES];
}
self.window.rootViewController = navVC; [self.window makeKeyAndVisible];
return YES;
}
If you're starting with a storyboard you need to have it set as your Main Interface in the Deployment Info in your app's General settings. You should also remove the line:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
..as it's initialising a new window in the place of the one created from the previous step.
I used these two lines of code to fix the issue. I got answer from here:
Programmatically set the initial view controller using Storyboards
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navVC = [storyboard instantiateViewControllerWithIdentifier:#"QuestionsView"];
I removed this line:
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
There don't get the error anymore.

Call View controller within Master-Detail template

I'm having trouble calling a newly created view controller within the storyboard. I have created an app using the default master-detail template. The only simple thing I'd like to do is call a new View Controller window when a specific check is valid/invalid (depending on requirement) (I refuse to use the term "Login" :-) ).
What is the best location to do this? In here (appDelegate)?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
UINavigationController *masterNavigationController = splitViewController.viewControllers[0];
MasterViewController *controller = (MasterViewController *)masterNavigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
} else {
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
MasterViewController *controller = (MasterViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
}
//Should I call the new view controller object from my storyboard at this location? (i.e. myView)
return YES;
}
I'm even considering starting all over without using the template of Xcode.
Do you need to use different controllers depending on check result?
If yes than there are few suggestions. You can cover your view with some activity view which covers all screen, wait for checking and than remove activity view.
Another thing you can try is making another view controller in storyboard and move starting arrow to it. You can try to login and after it perform correct segue.
And at least i can suggest to create root view controller programmatically.
something like this.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
levelViewController = [[LevelViewController alloc] init];
window.rootViewController = levelViewController;
[window makeKeyAndVisible];
}

How to assign NSManagedObjectContext from AppDelegate to ViewControllers in TabBased application?

newbie type of question here.
Since XCode doesn't provide project template for TabBased application with Core Data, so I have to go cutting and pasting Core Data stack from other templates to my TabBased application.
This is how to assign NSManagedObjectContext object from AppDelegate to MasterViewController in Master-Detail application template:
// AppDelegate.m (Master-Detail template)
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UINavigationController *navigationController =
(UINavigationController *)self.window.rootViewController;
MasterViewController *controller =
(MasterViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
return YES;
}
How to assign NSManagedObjectContext from AppDelegate to ViewControllers in TabBased application?
If the tab bar controller is the root view controller and
the "master view controller" is on the first tab:
UITabBarController *tbc = (UITabBarController *)self.window.rootViewController;
MasterViewController *controller = (MasterViewController *)tbc.viewControllers[0];
controller.managedObjectContext = self.managedObjectContext;
Update: If the first tab uses a navigation controller, you just have to insert one step:
UITabBarController *tbc = (UITabBarController *)self.window.rootViewController;
UINavigationController *nc = tbc.viewControllers[0];
YourViewController controller = (YourViewController *)nc.topViewController;
controller.managedObjectContext = self.managedObjectContext;
Create a property on your View Controller:
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext
Then say, for example you want to assign this for all view controller. You can do it by looping through the viewControllers of the UITabBarController.
UITabbarController *tabBarController = (UITabBarController *)self.window.rootViewController;
for (UIViewController *viewController in tabBarController.viewControllers) {
viewController.managedObjectContext = self.managedObjectContext
}

UISplitViewController and CoreData

I am working on a project that uses CoreData one-to-many relationship between folder and files. To show this I am using UISplitViewController, Folders are shown on MasterView and on click of each folder the files are shown on DetailView.Both folders and files are added dynamically.
I have programatically created UISPlitViewController this way
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
FolderViewController = [[FolderViewController alloc] initWithNibName:#"FolderViewController_iPad" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:FolderViewController];
FolderViewController.managedObjectContext = self.managedObjectContext;
fileViewController = [[fileViewController alloc] initWithNibName:#"fileViewController_iPad" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController: fileViewController];
FolderViewController.fileViewController = fileViewController;
self.splitViewController = [[UISplitViewController alloc]init];
self.splitViewController.delegate = fileViewController;
self.splitViewController.viewControllers = #[masterNavigationController, detailNavigationController];
self.window.rootViewController = self.splitViewController;
}
This splits my ipad in to two. Leftside is FolderViewController and rightside is FileViewController.
My master View never hides, in any Orientation.
I have a button on both Master and DetailView which opens common EditViewController modally through splitViewController this way
- (void)Buttonclick
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
testViewController = [[EditViewController alloc] initWithNibName:#"EditViewController" bundle:nil];
m_editViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[appDelegate.splitViewController presentModalViewController:m_editViewController animated:YES];
}
and when I dismiss this View, I add folders or files accordingly.
I dismiss this view this way
[self dismissModalViewControllerAnimated:YES];
I have few doubts here
1) When I launch the app, all imp(main) functions from Both View Controller gets called.is that ok?
2) When I dismiss this ModalView when opened from DetailView, the delegate functions of NSFetchResultsController get called, which are in MasterView . is that ok?
3) As those functions are getting called, my logic fails in some situations.
Regards
Ranjit

Resources