I have a split view controller with master view being something like a menu allowing users to pick the scene for detail view (I have multiple detail views). On one of the detailView scene, I have a button that presents a view controller modally and "Over Current Context" as it has a translucent background and I wanted to create that fog effect. This particular detailView (lets call it TodayViewController) is also the initial detail view controller when the app loads, and only changes when user selects a new view controller from the master view (menu).
This is what I meant in code:
When app just starts:
splitViewController.viewControllers[1] // returns TodayViewController
When user selects from the menu:
splitViewController.viewControllers[1] // returns a different view controller
So the issue I am having is that when the app just starts (bullet 1), when I present a child view controller of TodayViewController modally and "over current context", the child VC presents itself over both the master view (menu) as well as the detail view (TodayViewController), causing the entire screen to have a foggy effect. This is the effect that I want
However when I select another view controller (from the menu) and then select back TodayViewController and try to present the child VC it only presents itself over the detail view now. Meaning that the foggy effect is only present on the detail view and the master view (the menu again) remains clear. How do I fix this?
I hope I'm clear enough with my explanation. Here are some of my code:
My GlobalSplitViewController.swift:
import UIKit
class GlobalSplitViewController: UISplitViewController, UISplitViewControllerDelegate {
func primaryViewControllerForCollapsingSplitViewController(splitViewController: UISplitViewController) -> UIViewController? {
let detailViewController = self.viewControllers[1] as! TodayViewController
return detailViewController
}
func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController, ontoPrimaryViewController primaryViewController: UIViewController) -> Bool {
return true
}
func splitViewController(svc: UISplitViewController, shouldHideViewController vc: UIViewController, inOrientation orientation: UIInterfaceOrientation) -> Bool {
return false
}
}
GlobalSplitViewController is structured so that TodayViewController is presented first on iPhones, but on iPad it shows both master and detail view, uncollapsed.
'Over current context' is supposed to present over only the master or the detail wherever it is called from. I'm not sure why it doesn't work properly at first (but I understand that's what you want) but then works when you select another option. Anyhow, to achieve what you want, stop using 'over current context'. That will present the fog vc over the whole screen.
Related
I am trying to add the "Back button" to a couple of my view to a specific view that come before them.
View A has 2 buttons, to view B and C, I want B and C (And all following views) to have the "back button", but I don't want it to appear once I'm in view A.
In this example, I'll only show what I've done with view A and B.
I added the navigation controller between A and B, and as you can see, "Shows Navigation Bar" is ticked on. The segue between A and B is "present modally".
For some reason it doesn't show in my storyboard, but view A is a tabbed view connected to a tabbarController. What am I doing wrong ?
Your root view controller (first one, basically) needs to be a UINavigationController in order to have that navigation bar and back button work natively.
Also, presenting a UIViewController modally does not show a navigation bar (and subsequently the back button). Only when you push a UIViewController onto the navigation stack will the navigation bar and back button show.
Here is an example of pushing a view controller from another view controller that is within a UINavigationController:
func buttonPressed() {
let nextViewController = UIViewController()
self.navigationController?.pushViewController(nextViewController, animated: true)
// As long as your navigation bar is not set to hidden,
// doing this will push nextViewController onto the navigation stack
// and show the back button + navigation bar.
}
In my app i have a storyboard which has initial view controller as X and then i have a navigation controller which has couple of view controllers attached with it through segue but there is no connection between ViewController x and this navigation controller.
Now based on a button tap in View controller x i want to present this navigation controller.
I am doing this :
func showDashBoard()
{
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let next = storyBoard.instantiateViewControllerWithIdentifier("navigation") as! EBNavigationController
self.presentViewController(next, animated: true, completion: nil)
}
So the navigation view is getting presented with the root view controller but its not showing me animation and also i am getting a warning "Attempt to present on whose view is not in the window hierarchy!
"
Can some one please help me in figuring out what is the best way to do this.
Thanks,
The animation problem can be fixed using next.modalPresentationStyle and next.modalTransitionStyle. Lookup the enums for the possible values and give it the one you want.
You usually get the "Attempt to present on whose view is not in the window hierarchy!" errors when you are calling this function before the view is fully loaded. For instance if you call it in the viewDidLoad method. You should call it only after viewDidAppear is called.
I have an initial view controller. It goes to the next view controller which has the “picker wheel” in it. From that screen, if the user selects one of the 4 items in the picker wheel and stops on it. Then press ONE action button to initiate several C code statements.
I need specific help with coding the statement (s) that cause the transition from one view controller to another view controller.
I’m thinking out loud, it should look something like this (but I really don’t know):
‘If row = 0 then go to View controller B.’
‘If row = 1 then go to View controller C’
etc.
Or use some other ‘VERY SIMPLE’ method for transitioning from a ‘selection from a picker wheel to another view controller’.
Basic documentation.
I have 4 viewcontrollers :
First view controller is named - VCa
Second view controller is named - VC1
Third View controller is named - VCb
Forth view controller is named - Vcc
There is nothing but the default 'Storyboard" coding in this VCa (view controller).
The first view controller only has a label named VCa , so we can see which VC this is.
And it has a button named Button A, so I can do a modal segue to the next view controller named VC1.
The second view controller (VC1) only has some basic things.
The picker wheel named pickerView1. The array named Companies with data.
A button to go back to the first view controller VCa.
The button is named B1Back.
A button to go forward to the next view controller named VCb.
The pupose for this button is only for demo. purposes to transition to VCb.
It has nothing to do with coding a solution to allow the picker wheel selection to . transition somehow to the next view controller.
The button is named B1forwardtob.
The same is true for the 3rd button. It just allows this VC (VCa) to transition to . . another view controller named VCc. The button is named B1forwardtoc.
An ACTION button that does nothing, yet. I’m hoping the transition from view controller to view controller code goes here (after the action button). But again I don’t know what I don’t know.
There is nothing but the default 'Storyboard" coding in this VCb (view controller).
The third viewcontroller (VCb) is very simple too. It is there just to go to and then go back to VC1.
There is nothing but the default 'Storyboard" coding in this VCc (view controller).
Same for the forth viewcontroller (VCc). It is there just to go to and then go backto VC1.
It's sort of hard to tell what you're asking, but are you looking for something like this?
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
UIViewController *viewControllerToDisplay;
if (row == 0) {
viewControllerToDisplay = [[ViewControllerB alloc] init];
} else if (row == 1) {
viewControllerToDisplay = [[ViewControllerC alloc] init];
}
if (viewControllerToDisplay) {
[self presentViewController:viewControllerToDisplay animated:YES completion:nil];
}
}
(Xcode6-beta3, Swift, iOS8, iPad)
In an iPad split-view controller, how do I link the Master View Controller to the Detail View Controller?
In other words, when the user taps on an item on the left, how do I change the view on the right?
I know that in didSelectRowAtIndexPath, I need to call a method... but how do I call a method in the Detail View Controller from the Master View Controller?
Example
Imagine an app to display information on different types of cheeses. We begin by dragging a split-view controller onto the storyboard. A table of items in the master view on the left is set up to read as follows.
Swiss
Cheddar
Brie
On the right, there is simply a Web View inside of the detail view controller, named cheeseViewController. Therein, HTML documents about the selected cheese will be displayed.
An IBOutlet is wired from the web view into cheeseViewController, and a method named 'changeCheese' is set up in the Detail View Controller delegate to swap out the document.
How can I make a tap on "Cheddar" change the information in the detail view?
EDIT: Do I have to modify my AppDelegate.swift file? Using a Master-Detail template, I tried the following, with no luck:
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
// Override point for customization after application launch.
let splitViewController = self.window!.rootViewController as UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as UINavigationController
splitViewController.delegate = navigationController.topViewController as Paragraph
return true
}
I hope I understood your problem correctly: You would like to show the detail information of a selected cheese in your Detailview.
When you create a new Master-Detail-View application in XCode 6 Beta 3, there will be a variable called "detailItem" in your DetailViewController.Swift file:
var detailItem: AnyObject? {
didSet{
self.configureView()
}
You set this detailItem in your MasterViewController.Swift file in the following function:
override func prepareForSegue(segue: UIStoryBoardSegue, sender: AnyObject?){
if segue.identifier == "yourSegueIdentifier" {
let indexPath = self.tableView.indexPathForSelectedRow()
let cheeese = yourCheeseArrayWithDetailInformation[indexPath.row]
(segue.destinationViewController as DetailViewController).detailItem = cheeese
}
}
(Assuming, that you have linked the views with a segue with the identifier: "yourSegueIdentifier" and an array of detailinfo called "yourCheeseArrayWithDetailInformation")
The above mentioned function "configureView" in the DetailView can now access your detailItem, which contains the contents of "cheeese"
I hope this helps you.
Why don't you just post a Notification from didSelectRowAtIndexPath in your Master and add an observer in your Detail View most likely inside your viewDidLoad. You also can handle the selector within the observer method with closure.
If you didn't create a master-detail app (so you have no detailItem), you might use this:
if let
mySplitViewController = splitViewController,
detailView = mySplitViewController.childViewControllers.last as? DetailViewController {
// do something with it
}
First of all, let me say I'm an absolute beginner, so please forgive me if this is a stupid questions to be asking. And let me just add that I've spent hours/days trying to figure out how to solve this problem - including extensive searches on stackoverflow (maybe the answer is somewhere and I just don't now exactly what to search for :)...
But, let's continue: I have a small (?) problem with an Xcode storyboard project. Basically my project looks like this:
Navigation Controller -> View Controller 0 -> Tab Bar Controller -< View Controller 1, View Controller 2, View Controller 3.
When the user pushes 'button #2' in the View Controller 0, I'd like him/her to jump directly to 'View Controller 2'.
Would that be possible at all, and if so what code should use and excatly where should I put it.
Hope someone out there will help a newbie out :)
Regards,
Ulrik
Yes it is possible. You may show any view controller from any other.
You should simply add a segue from button #2 to View Controller 2. (I assume you have all your controllers in single storyboard)
Update: the above solution will show you View Controller 2 itself without tab bar controller.
Hard to tell in details without seeing the actual code. For more details you may refer to these documents:
View Controller Basics (especially part "Storyboards Help You Design Your User Interface")
Presenting View Controllers from Other View Controllers
Using View Controllers in Your App
Probably you'll come up with more concrete question.
Update
If you want to preselect desired view controller inside tabbar controller you may use the following code sketch. Here you can programmatically initiate a segue and do the desired pre-initialization inside prepareForSegue:sender: method.
static NSString * const kShowTabSegueID = #"ShowTab";
#interface ViewController ()
- (IBAction)buttonOnePressed;
- (IBAction)buttonTwoPressed;
- (IBAction)buttonThreePressed;
#end
#implementation ViewController
- (IBAction)buttonOnePressed
{
[self performSegueWithIdentifier:kShowTabSegueID
sender:#0];
}
- (IBAction)buttonTwoPressed
{
[self performSegueWithIdentifier:kShowTabSegueID
sender:#1];
}
- (IBAction)buttonThreePressed
{
[self performSegueWithIdentifier:kShowTabSegueID
sender:#2];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
if ([segue.identifier isEqual:kShowTabSegueID]) {
NSNumber *indexToShow = sender;
UITabBarController *tabBar = segue.destinationViewController;
[tabBar setSelectedIndex:indexToShow.unsignedIntegerValue];
}
}
#end
If you are simply trying to programatically switch tabs, its as simple as:
[self.tabBarController setSelectedIndex:1];
If I am understanding your flow correctly, from ViewController0 you would present ViewController1(that has a UITabBarController). In the viewWillAppear: set the selectedIndex for the tab controller (code above) to index 1, which would be ViewController2.
EDIT
After looking at your project, add this code to your BrainBreaksViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[self.tabBarController setSelectedIndex:1];
}
I added this, and it switches to the 2nd tab after pressing "Press this button to goto tab #1". Follow Max Ks answer if you would like to be able to have a button to open each specific tab.
So if I understand correctly you have a view controller outside the tabbar controller and you want to navigate to the second tab in the tabbar controller from that (outside)view controller, if that is the problem then, this is my solution and I hope it helps someone as I spent some time on this issue myself.
First connect the (outside)Viewcontroller 0 to the tabbar controller in the storyboard with modal segue and give it identifier - "showTabBar" (not as one of the tabs just a modal segue).
Then:
in Viewcontroller 0 declare:
var tabBarIndex: Int?
//function that will trigger the **MODAL** segue
private func loadTabBarController(atIndex: Int){
self.tabBarIndex = atIndex
self.performSegue(withIdentifier: "showTabBar", sender: self)
}
//in here you set the index of the destination tab and you are done
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showTabBar" {
let tabbarController = segue.destination as! UITabBarController
tabbarController.selectedIndex = self.tabBarIndex!
}
}
then you can navigate to ViewController 2 like that(don't forget it is 0 indexed):
self.loadTabBarController(atIndex: 1)
This is tested and working as of the day I am posting this answer using
Swift 3.0.2 / Xcode 8.2.1