UISplitViewController and CoreData - ios

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

Related

iOS MMDrawerController objective-c login view controller

I am begin to study iOS and I try to do left navigation with MMDrawerController
my AppDelegate didFinishLaunchingWithOptions code is:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *leftView = [mainStoryboard instantiateViewControllerWithIdentifier:#"LeftViewController"];
UINavigationController *leftNav = [[UINavigationController alloc]initWithRootViewController:leftView];
UIViewController *centerView = [mainStoryboard instantiateViewControllerWithIdentifier:#"CenterViewController"];
UINavigationController *centerNav = [[UINavigationController alloc]initWithRootViewController:centerView ];
self.drawerController = [[MMDrawerController alloc] initWithCenterViewController:centerNav leftDrawerViewController:leftNav];
self.drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModePanningCenterView;
self.drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModePanningCenterView;
self.window.rootViewController = self.drawerController;
[self.window makeKeyAndVisible];
// Override point for customization after application launch.
return YES;
}
So it's work fine, but I have LoginViewController on my app, and if user has no saved token on NSUserDefaults, I must show LogionViewController.
Of course side menu must be hidden on LoginViewController.
I Tried to switch to LoginViewController inside my CenterViewController:
- (void)viewDidLoad {
[super viewDidLoad];
LoginViewController * vc = [[LoginViewController alloc] init];
AppDelegate *app = [[UIApplication sharedApplication] delegate];
[app.drawerController setCenterViewController:vc withCloseAnimation:YES completion:nil];
}
But I have black screen only.
What I do wrong?
Thanks
What you're doing is a bit weird because you are setting the new centerViewController (of type LoginViewController) within the current one (of type CenterViewController), and once that is done the latter one will be deallocated because there are no more references to it. This might somehow be causing the black screen.
One solution would be to have the LoginViewController outside the MMDrawerController, and always present it at the beginning. If there is no token, then quickly (without animation) present the MMDrawerController and the LoginViewController won't even be seen. This way also allows you to easily dismiss back to the login screen if the user logs out.
Another option is to just present your LoginViewController from the CenterViewController modally (or however you like really) using presentViewController:animated:completion:, and then just dismiss it when they log in.

Creating UITabBarController in a UINavigationController

My app has a drawer menu view and some content views.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
// Side menu view controller
UIViewController *menuViewController = [storyboard instantiateViewControllerWithIdentifier:#"sidebar_menu"];
UINavigationController *menuNav = [[UINavigationController alloc] initWithRootViewController:menuViewController];
// The initial content view controller
UIViewController *contentViewController = [storyboard instantiateViewControllerWithIdentifier:#"content1"];
UINavigationController *contentNav = [[UINavigationController alloc] initWithRootViewController:contentViewController];
NVSlideMenuController *slideMenuController = [[NVSlideMenuController alloc] initWithMenuViewController:menuNav andContentViewController:contentNav];
slideMenuController.slideDirection = NVSlideMenuControllerSlideFromRightToLeft;
self.window.rootViewController = slideMenuController;
[self.window makeKeyAndVisible];
}
I want to insert a tab bar controller programatically to content view. I want the change the current content view to another content view when the tab bar item button pressed.
Is it possible to create this kind of structure? How could I achieve this?
You simply need to code that you've just described in the question. Here is how you can modify your code to add UITabBarController that wraps your contentViewController, I've changed The initial content view controller section:
// The initial content view controller
UIViewController *contentViewController = [storyboard instantiateViewControllerWithIdentifier:#"content1"];
[contentViewController setTabBarItem:[[UITabBarItem alloc] initWithTitle:#"My Content" image:[UIImage new] tag:1]];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:#[contentViewController/* you can add more view controllers if needed*/]];
UINavigationController *contentNav = [[UINavigationController alloc] initWithRootViewController:tabBarController];

Disable/hide root view controller for one view controller

I'm having troubles hiding the UITabBarController which I defined as my rootViewController for the entire app.
I'm trying to hide the UITabBarController - which is the root view controller for the entire app - on the first view displayed. The idea is that the first view has UIImageView instances which jump to the defined UIViewControllers (which are also defined as view controllers of the root UITabBarController).
Is there a way to have the first view controller without the root UITabBarController but keep it for all other views defined as viewControllers?
Here's the code in AppDelegate defining the view controllers and the UITabBarController as rootViewController.
- (void)initViewControllers {
anIdeaVC = [[IdeaViewController alloc] initWithNibName:#"IdeaViewController" bundle:nil];
[anIdeaVC setTabBarItem:[[[UITabBarItem alloc] initWithTitle:#"Idea" image:[UIImage imageNamed:#"iconIdee.png"] tag:0] autorelease]];
aListTableVC = [[ListTableViewController alloc] initWithStyle:UITableViewStylePlain];
[aListTableVC setTitle:#"List"];
aListNC = [[ListNavigationController alloc] initWithRootViewController:aListTableVC];
[aListNC setTabBarItem:[[[UITabBarItem alloc] initWithTitle:#"List" image:[UIImage imageNamed:#"iconList.png"] tag:0] autorelease]];
anInnMapVC = [[MapViewController alloc] initWithNibName:#"MapViewController" bundle:nil];
anInnMapNC = [[InnMapNavigationController alloc] initWithRootViewController:anInnMapVC];
[anInnMapNC setTabBarItem:[[[UITabBarItem alloc] initWithTitle:#"InnMap" image:[UIImage imageNamed:#"iconInnMap.png"] tag:0] autorelease]];
aSearchTableVC = [[SearchTableViewController alloc] initWithNibName:#"SearchTableViewController" bundle:nil];
[aSearchTableVC setTitle:#"Search"];
aSearchNC = [[SearchNavigationController alloc] initWithRootViewController:aSearchTableVC];
[aSearchNC setTabBarItem:[[[UITabBarItem alloc] initWithTitle:#"Search" image:[UIImage imageNamed:#"iconSearch.png"] tag:0] autorelease]];
tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:anIdeaVC, aListNC, anInnMapNC, aSearchNC, nil] animated:NO];
[tabBarController setSelectedViewController:anIdeaVC];
[tabBarController setDelegate:self];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self initViewControllers];
[window setRootViewController:tabBarController];
[window makeKeyAndVisible];
return YES;
}
Thanks in advance for your help :-).
I think the best way to go about this is to make the vc with the icons the root to begin with. Then, when user makes a selection, create the tab bar vc and make it the root.
Create a view controller (not just a view) to show the icons and get the user selection. Make that the window's root on launch...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// don't do this
//[self initViewControllers];
// or this
//[window setRootViewController:tabBarController];
// instead do this, create the vc that lets user select an icon
// put your icon view in there
IconSelectVC *iconSelectVC = [[IconSelectVC alloc] init];
[window setRootViewController:iconSelectVC];
[window makeKeyAndVisible];
return YES;
}
Add the initViewControllers method to your app delegate's public interface, so it can be called from IconSelectVC. Then add one last line to it to make it replace the window's root vc.
// ... the rest of initViewControllers, then
[tabBarController setSelectedViewController:anIdeaVC];
[tabBarController setDelegate:self];
[window setRootViewController:tabBarController];
}
Now, in your IconSelectVC when you decide it's time to change the UI, get the app delegate singleton and change the window's root.
// in IconSelectVC.m
// when you decide to change to the tab bar.
// Be aware that this vc will be released here, so do any cleaning you need to do here
// e.g. unsubscribe from NSNotifications, clean any timers, finish any asynch requests, etc.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate initViewControllers];
EDIT - We didn't discuss how this transition should look - my suggestion here will cause an "ugly" transition (in the eye of the beholder, of course) where the UI just changes in one frame. One way (among a few) to get a nicer transition would be to use os7 custom vc transitions.

Strange behaviour of UINavigationController when the applications rootViewController is a tabBarController

I try to push a UIViewController onto a UINavigationController. The NavigationBar changes (i.e. a back-button appears) but the view is not pushed (*).
I have a UITabBarController as my applications RootViewController.
When I switch to another tab and then switches back, the view (*) gets pushed.
I have never seen this behaviour before. My problem is exactly the same as this, however the methods that solved that issue did not solve mine.
Initially
After I press the row
I understand that this question might be related to issues in AppDelegate, therefore i post the code I use.
Code:
in AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[MagicalRecord setupCoreDataStackWithStoreNamed:#"DBModel"];
/* CONTACTS LIST CONTROLLER */
BoonContactListViewController *contactListViewController = [[BoonContactListViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *contactListNavigationController = [[UINavigationController alloc] initWithRootViewController:contactListViewController];
[contactListNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
contactListNavigationController.tabBarItem.title = [NSLocalizedString(#"CONTACTS", nil) capitalizedString];
contactListNavigationController.tabBarItem.image = [UIImage imageNamed:#"menu_contacts.png"];
/* INVITATIONS */
BoonInvitationListViewController *invitationListController = [[BoonInvitationListViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *invitationNavigationController = [[UINavigationController alloc] initWithRootViewController:invitationListController];
[invitationNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
invitationNavigationController.tabBarItem.title = [NSLocalizedString(#"SETTINGS", nil) capitalizedString];
invitationNavigationController.tabBarItem.image = [UIImage imageNamed:#"menu_invitations.png"];
/* SETTINGS */
BoonSettingsViewController *settingsViewController = [[BoonSettingsViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *settingsNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
[settingsNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
settingsNavigationController.tabBarItem.title = [NSLocalizedString(#"SETTINGS", nil) capitalizedString];
settingsNavigationController.tabBarItem.image = [UIImage imageNamed:#"menu_settings.png"];
/* TAB BAR */
BoonTabBarViewController *tabBarController = [[BoonTabBarViewController alloc] init];
tabBarController.viewControllers = #[contactListNavigationController, invitationNavigationController, settingsNavigationController];
[self.window setRootViewController:tabBarController];
[self.window makeKeyAndVisible];
[tabBarController showLogin];
return YES;
}
EDIT:
In the viewController that i am trying to push, neither viewWillAppear, viewDidLoad nor viewDidAppear is called.
If I use presentViewController: animated: completion: I get the preferred behaviour, id rather not though
EDIT 2
How I push my new VC
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
BoonContactInfoViewController *contactInfoViewController = [[BoonContactInfoViewController alloc] initWithNibName:nil bundle:nil];
NSLog(#"NAV %#", self.navigationController);
[self.navigationController pushViewController:contactInfoViewController animated:YES];
}
EDIT 3
It is only the initial tab that cannot push ... if i swap places of the first and second tab, i can push a view controller using in the way i do above.
EDIT 4
It works if i (in my tabBarController) calls
self.selectedIndex = 1;
self.selectedIndex = 0;
EDIT 5
- (void)showLogin
{
if([BoonUserHandler getLogin].length > 0 && [BoonUserHandler getPassword].length > 0){
return;
}
BoonWelcomeViewController *welcomeWC = [[BoonWelcomeViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *welcomeNavigationController = [[UINavigationController alloc] initWithRootViewController:welcomeWC];
[welcomeNavigationController setNavigationBarHidden:YES];
[self presentViewController:welcomeNavigationController animated:NO completion:nil];
}
What version of iOS are you developing for?
I'd first ask why you're hacking in a nav bar using:
[settingsNavigationController setValue:[[BoonNavigationBar alloc]init] forKeyPath:#"navigationBar"];
rather than the iOS5+ UINavigationController method:
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
But my overall suggestion would be to remove all this code and use a storyboard. This looks like the perfect opportunity.
I think you are getting wrong Navigation controller to push that's why it showing this problem..
You have to fetch right navigation controller from tab controller
self.tabBarController.selectedIndex = 0;
just change tab controller selected index

Tabbed application won't show Login view

I have a tab bar application in Xcode 4.3 and I'm trying to insert a login screen before the tabbar is shown. The app works OK if presentModalViewController has animated:YESbut if it is without animation the view is not showing.
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
LogInViewController *logViewController = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self.window addSubview:_tabBarController.view];
[self.tabBarController presentModalViewController:logViewController animated:YES];
//This wont work
//[self.tabBarController presentModalViewController:logViewController animated:NO];
[self.window makeKeyAndVisible];
return YES;
}
-(void)loginDone{
NSLog(#"back to the app delegate");
[self.tabBarController dismissModalViewControllerAnimated:YES];
}
Is this the right way to do it?
Why wont the code work with animated:NO ?
I also get this on output Unbalanced calls to begin/end appearance transitions for <UITabBarController: 0x689d350>.
First of all, move [self.window makeKeyAndVisible]; before your view controller setup.
Additionally, you should be presenting the modal view controller within the viewWillAppear: method of the view controller that will be visible first, to make sure your apps view hierarchy has been fully initialized before presenting your login screen.
Don't do this:
[self.window addSubview:_tabBarController.view];
Do this:
self.window.rootViewController = _tabBarController;
This will put the tabBarController on the screen. But that's not exactly what you want... My advise is:
1) Start by putting the logViewController has the rootViewController as I showed you above.
2) Once you got what you want (login is successful) just tell the AppDelegate to switch the rootViewController. This can be done in with delegation or notifications.
Also, as Toastor indirectly pointed out, you should start the presentViewController from the UIViewController who actually initiates it (and not from the AppDelegate).

Resources