I have an app that I just got setup with a split view controller to display blogs on the ipad version of the app. The current setup is master controller is a table view to show the different articles off the blog, and the detail controller is a view controller with a webview inside used to show the content of the article. The issue is that I have a few other features in the app, and on the iPhone version, I use a tab bar controller to navigate. What would be some options to add buttons to the detail controller that would allow me to navigate to the other sections of the app? I know I can't get a Tab Bar Controller within the Split View Controller so I just need some guidance.
I know that the Engadget app is setup so that when you open in portrait mode, it shows the table view of apps, along with a controller at bottom to go to different things like photos, and when in landscape the table view is on the left and the text of the articles is on the right. I just want it set up so there is no blank page if you open in portrait mode, and have a feature to view other pages, besides just adding buttons to the navigation bar.
you CAN add a tabBarController to your SplitViewController's detail view. Simply create a UIViewController that responds to <UITabBarControllerDelegate> and in the xib file for that controller add a UITabBarController object and link it to your UIViewController. In your viewDidLoad add the Tab bar controller to the view:
-(void)viewDidLoad {
...
[self addChildViewController:myTabBarController];
//add the tabBarController view
[self.view addSubview:myTabBarController.view];
}
This UIViewController will be assigned to your detail view. this works and I've tried it before. However, whether apple would allow it? i don't know!
EDIT:
first of you should never call viewDidLoad yourself.
Also, i don't think you need rootipad and detailipad as long as the controllers are linked to the SplitViewController in the xib file.
in your RootViewiPad (master) add the following inside its viewDidLoad :
-(void)viewDidLoad {
...
if (self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
//select the first row to load
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
//NOTE, I'm assuming that selecting the cell will load the detail view.
//if that is not the case, you need to do what ever you need to load the
//detail view.
}
}
if you want this behavior to happen every time (not only on first load) then add the code to the -(void)viewWillAppear method instead.
Related
I have App with single storyboard, and two view in same story board. First one is controlled by ViewController and second one is controlled by View.(Two different class files, one inherits UIViewController and another UIView). App loads the first story board which is linked to UIViewController.
Now, I want to check some conditions in NSUserDefaults and skip the first view on app load if the condition is true. Skip first view can also be automatically load second view, this what I am trying to accomplish.
I have searched a lot and all of them were about the Navigation Controller, My views/controllers are not navigation controller, also I dnt want to use that because of the automatic navigation bar which I dont want.
Please help! Thanks.
remember to import the secondView,
and in storyboard you have to give the identifier "SecondView" to secondViewController
if ([[NSUserDefaults standardUserDefaults]boolForKey:#"Yes"]) {
SecondViewController *sv = (SecondViewController *)[self.storyboard
istantiateViewControllerWithIdentifier:#"SecondView"];
sv.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:sv animated:YES completion:Nil];
}
Just to clarify things, I don't want to use UITabBarController. I need to do some custom changes to the UITabBar that can't be done using UITabBarController. (like making it scroll etc')
This is how I've created my UITabBar
From the Interface Builder I've dragged a UITabBar and located it inside a ViewControllers.
Connected the delegate and outlet.
Added UITabbarItem tags and segue identifier.
and used this code:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
if (item.tag==0) {
[self performSegueWithIdentifier:#"Favorite" sender:nil];
}
else if (item.tag==1)
{
[self performSegueWithIdentifier:#"Item" sender:nil];
}
}
My problem is that when I push a new ViewController the UITabBar disappears.
My question is, what's the right proper way to keep the UITabBar on the pushed ViewController and other ViewControllers ?
I've tried passing it to the next view controller using PrepareForSegue and it works but when I go back to my previous controller I need to reset the UITabBar frame etc'. I guess I can keep it as a global object inside my Singleton and keep adding it to new ViewControllers but that sounds like an over kill
Is there a better way to do it without using a UITabBarController ?
Even if you don't want to use a tab bar controller, you should still follow the same design pattern. Your ScrollableTabBarController should be a container view controller, and when different tab items are selected, it should add the new item as a child view controller. Read the view controller containment documentation for more details.
At the moment it sounds like you're pushing view controllers on top of your container, which suggests that your storyboard is based on a navigation controller. This is the wrong way to do it.
I'm not sure how straightforward it is to do custom container controllers in the storyboard, (I'd do it in code). You may have to make the connections manually rather than via segues.
I have a view controller which displays a carousel control (iCarousel). The view is rendered correctly and the carousel is displayed. Right after that a modal is displayed which allows the user to agree to certain terms. I want that once they agree I refresh the viewcontroller which contains the carousel control. Basically, I want to rotate the carousel to some random index.
- (IBAction)accept:(id)sender
{
NewsViewController *newsViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"NewsStoryboard"];
[newsViewController loadNews];
[newsViewController.view setNeedsDisplay];
[self dismissViewControllerAnimated:YES completion:nil];
}
The above code does call the loadNews and fetches it but the view is never refreshed.
What happens to the carousel should really be up to the view controller that manages it, not the modal view controller. Make the modal controller do its thing and return whatever data it collects to its parent. The parent (in this case, the carousel's controller) can then look at that data and decide what it needs to do next (refresh, for example).
The problem is this line:
NewsViewController *newsViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"NewsStoryboard"];
That is not the old view controller; it is a new, unused copy of that view controller. You need to create a line of communication from the modal view controller back to the existing view controller.
The typical way to do this is through a delegate, which you set when creating the modal view controller. If you look at the Xcode Utility template, you will see that it illustrates this architecture. The original view controller sets itself as the modal view controller's delegate, and the modal view controller is thus able to talk back to the original view controller as it is dismissed.
This is such an important thing to be able to do that I talk about it at length in my book:
http://www.apeth.com/iOSBook/ch19.html#_presented_view_controller
I have an iPad application that has a button on one view. When I press the button I want it to load a second view. The second view I am trying to load is a CollectionView. I am not using, and do not want to use a UINavigationController.
Does anyone know how to load a second view on a button tap? Also, I will want to create a Back button that will go back to the previous view. The previous view could be different each time the button is tapped.
There is a decent amount of material online about this topic, but I can't find anything that will work or anything that is recent.
Here is the code I have now:
-(void)showCollectionView:(id)sender
{
NSLog(#"In ShowCollectionView");
ZHCollectionViewController *cvc = [[ZHCollectionViewController alloc]
initWithNibName:#"ZHCollectionViewController"
bundle:[NSBundle mainBundle]];
[self.view addSubview:cvc.view];
NSLog(#"After all the stuff");
}
When this runs both NSLog's are executed and the message shows up in the console, but nothing happens to the view.
Yo can try to present it modally:
[self presentViewController:cvc animated:YES completion:^{
}];
Before this call you can customize appearance of your 'cvc' by defining transition and presentation styles, for example:
cvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cvc.modalPresentationStyle = UIModalPresentationFormSheet;
To hide it call in ZHCollectionViewController, inside some button action I believe
[self dismissViewControllerAnimated:NO completion:^{
}];
There are several ways to do this, and the way you're trying isn't one of them. If you just want to add a view, not a view controller, you should have a xib file that is a view, not a view controller. You would have to make the controller whose view you're adding this collection view into, the files owner of this collection view, so you can hook up any outlets to it.
It's not correct to add another view controller's view to your view, unless you're making that controller a child controller. If you want ZHCollectionViewController to be the controller of the collection view, then you should add that controller as a child view controller. You can check out Apple's documentation on custom container controllers to see how that's done.
You didn't really say in your question, how this collection view is to appear. Do you want it to take up the whole screen, or do you want it to be a subview? If you want it to take up the whole screen, then it would be better to just change the window's root view controller to ZHCollectionViewController, or present it modally over the current view.
I'm having a problem getting a UISearchDisplay's text value to be set programatically on load of the view by another view and my question is have I overcomplicated my problem and missed something or am I on the right track of thinking.
Here's the situation: I have a UITabBarController as my root view, there are 2 tabs, both have a UINavigationController setup so I can push views as needed.
Tab 1 has a UITableViewController which is populated with a list of categories.
Tab 2 has a MapView in it's main view but I have done a custom UINavigationItem view to put various buttons and a UISearchDisplay on the rightBarButtonitem area.
The mapview layout and custom navigation item are stored in the same nib as two separate view objects. In Tab 2's viewDidLoad(), I initialise the rightBarButtonItem programatically with:
UIBarButtonItem *btnItem = [[UIBarButtonItem alloc] initWithCustomView:buttonBar];
self.navigationItem.rightBarButtonItem = btnItem;
[btnItem release];
Everything fires up, buttonBar is wired up to an IBOutlet as searchWhat and I can talk to this object from within the mapview's controller class.
If the user is in Tab 1 and taps a cell, I want it to switch to Tab 2 and populate the searchWhat.text and then execute the search code as if someone had typed in the search themselves.
What i'm having trouble with is the order of load and populate on a view.
I can access the 2nd tab from the 1st without any problem and get it to appear with something like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Quick Category cell tapped at row %d", indexPath.row);
self.tabBarController.selectedIndex = 1; // change to the search view controller
//[self.tabBarController.selectedViewController viewDidAppear:YES];
UINavigationController *nav = (UINavigationController *)self.tabBarController.selectedViewController;
SearchViewController *srch = [nav.viewControllers objectAtIndex:0];
//NSLog(#"%#", [srch description]);
[srch queueSearchByType:kSearchTypeQuickCategories withData:[catList objectAtIndex:indexPath.row]];
[srch viewDidAppear:YES];
}
Don't worry about catList and SearchViewController, they exist and this bit works to switch tabs.
Here's the problem though, if the user starts the application and selects an item in tab 1, tab 2 appears but the values of the search display text don't get set - because viewDidLoad and viewDidAppear are called in another thread so the execution of queueSearchByType:withData: gets called while the view is still loading and setting up.
If the user selects tab 2 (therefore initialising the subview) and then selects tab 1 and an item, it can populate the search display text.
I can't just change the order of the tabs so that tab2 is first and therefore loads it's subviews to the navigation bar as the project specification is category search first.
Have I missed something very simple? What I need to do is wait for the second tab to fully appear before calling queueSearchByType:withData: - is there a way to do this?
At the moment, i've implemented a queue the search, check for a queue search approach, this seems to be a bit long winded.
Ok, I don't like answering my own question but it appears my fears were right, basically if you want a UINavigationItem that is a custom view (ie, to put a search bar and various other buttons up on the nav controller) and be able to switch to and populate them from another tab on a tab bar controller, then you need to put the subview in it's own class which is a subclass of UIViewController and then make delegation your friend (which it already is), i've provided an example in case anybody needs to repeat it which i've put on my blog HERE.
http://www.jamesrbrindle.com/developer/ios-developer/howto-add-a-custom-uinavigationitem-to-a-uinavigationcontroller-with-delegation.htm
If anyone disagrees and thinks this can be simpler, please let me know or rate this post