I'm trying to program an iOS App in Swift, where there would be a splash screen before the tab bar screen.
I've looked at:
http://sweettutos.com/2014/01/08/present-a-login-screen-before-the-tab-bar-controller-in-a-uitabbarcontroller-based-app/
Loading a Welcome Screen (Splash Screen) before TabBarController
but both of them require a nib file and I did all my UI in storyboard.
Here's my main question:
The code on the website has something like this:
ControllerName(nibName: "NibName", bundle: nil);
Is there any way I could do the same thing without the nib file and use storyboard?
Assuming that you have the TabBarController already in storyboard, you would add another view controller next to it.
Then you would click on the new view, and in the attributes inspector, check off "Is initial View Controller".
That makes that new view the first thing that comes up when the app is opened. To go to the tabBarController, I would probably have some button on that first view that just has a segue(control drag) to the TabBarController.
What you can do is the following the example in which the tab bar view controller is set as initial viewcontroller you can
Drag and drop another UIViewController from the Object Library into the storyboard object library.
Click on the UIViewController and assign it a StoryboardID
StoryboardID.
In your first view controller class you can access the storyboard and create an instance of the new view controller, that you dragged and dropped before, using the storyboard id, you can do it this in the viewDidAppear override function and present the new view controller modally.
override func viewDidAppear(animated: Bool) {
let myStoryboard = self.storyboard
let modalViewController = myStoryboard?.instantiateViewControllerWithIdentifier("ModalViewControlllerID")
presentViewController(modalViewController!, animated: true, completion: nil)
}
To instantiate programmatically a viewController from a storyboard in a similar way as you would do from a xib with ControllerName(nibName: "NibName", bundle: nil), it's:
UIStoryboard(name: "StoryboardName", bundle: nil)
.instantiateViewController(withIdentifier: "ControllerName")
But you must not forget to set the arbitrary identifier of your viewController in the storyboard under Storyboard ID:
Drag navigationController and viewController to storyboard and make navigationcontroller as initial viewcontroller then push tabbarcontroller from viewcontroller.
Thanks,
Nada Gamal
I just needed to do the same for my project. Here is my solution.
I created a ViewController and made it the Storyboard Entry Point in the Main.storyboard. I previously had a TabViewController with all kinds of setup and needed only 1 change there.
TabBarController should have a StoryboardID, I named my "TabBarID".
I created a new LaunchViewController swift file with that new ViewController added to my Main.storyboard and assigned it in Main.storyboard.
Here is that class. Very simple with a timer that once over the threshold will then present the TabBarViewController in fullscreen.
class LaunchViewController: UIViewController {
var timer = Timer()
var time = 0
var threshold = 2
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundTheme(theme: .orangeWhite)
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}
#objc func updateTimer() {
time += 1
if time > threshold {
timer.invalidate()
guard let storyboard = self.storyboard else {
//failed to find storyboard
return
}
let tabBarController = storyboard.instantiateViewController(identifier: "TabBarID")
tabBarController.modalPresentationStyle = .fullScreen
present(tabBarController, animated: true, completion: nil)
}
}
}
Related
In my app I use side bar as in facebook. when the user slides out the side bar a uiimageview is displayed. when user taps on the image it takes hm to a different viewcontroller. the problem i am facing is that I have created sidebar programatically and the other view to which I want to navigate the user is created using storyboard. So my source view is created programatically and destination view is created using storyboard. So can someone explain me if there is any way of using "Segue" in this scenario. Since i can not create segue using storyboard I need to do it programatically but even after a lot of googling i could not find the answer.
Well, to get another instance of another storyboard programmatically you can use something like:
let newController = UIStoryboard(name: "MyStoryboard", bundle: nil).instantiateViewControllerWithIdentifier("MyIdentifier") as! MyViewController
and then you push to your navigation controller, or add as a child view controller or something...
If you don't wanna bother with identifiers you can just use the instantiateInitialViewController instead of instantiateViewControllerWithIdentifier
Might help
"userSB" is the viewcontroller storyboard identifier
#IBAction func tapSearchCriteria(_ sender: Any?) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let aVC = storyboard.instantiateViewController(withIdentifier: "userSB") as? AViewController
aVC?.modalPresentationStyle = UIModalPresentationStyle.custom
aVC?.transitioningDelegate = self
aVC?.udelegate = self
self.present(aVC!, animated: true, completion: nil)
}
I've just created a tab UIViewController in Swift, brand new, no code.
I wanted to know how I could change which tab the app starts on. For example, it has view 1 and view 2. At the bottom it has two tabs, tab 1 and tab 2. How could I get it to where the tab and page it starts on is tab 2, view 2. Instead of always opening and starting on the first tab. Thank you for the help!
i think its natural that the UITabViewController shows the first UIViewController.
edit:
The best solution is to subclass the UITabBarController and to change the selected index in it's viedDidLoad() Delegate:
Create a subclass file of UITabBarController (File -> New -> File -> Cocoa Touch Class)
Set this new file as the Class in the UITabBarController of your Storyboard.
Add in the new file:
override func viewDidLoad() {
super.viewDidLoad()
tabBarController.selectedIndex = 1
// or: tabBarController.selectedViewController = myViewController
}
Here's a possible solution. In your viewWillAppear method.
override func viewWillAppear() {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Enter your tabBar storyboard ID here") as! UITabBarController
vc.selectedIndex = 0
self.presentViewController(vc, animated: true, completion: nil)
}
The selectedIndex 0 is the first tabBar. You can change this to whichever tabbar you want to open
Set a storyboard ID in main.storyboard identity ID
I have just made a small transition so my project loads a different storyboard as its main (did it in the info.plist).
I have my new storyboard to keep my viewController that are responsible for login screen etc. Just to make it more clear.
After the login button is tapped I want to initiate a navigationController from another storyboard:
func instantiateViewController(fromStoryboard storyboard: String, withIdentifier identifier: String) -> UIViewController! {
let storyboard = UIStoryboard(name: storyboard, bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier(identifier)
return viewController
}
#IBAction func loginButtonTapped(sender: UIButton) {
let viewController = instantiateViewController(fromStoryboard: "Main", withIdentifier: "MainNavigationController")
presentViewController(viewController, animated: true, completion: nil)
}
Everything works correctly but one thing is driving me nuts.
After presenting the MainNavigationController from Main.storyboard its view hierarchy is not maintained.
What I mean is, the labels and buttons which supposed to be on top of another, full screen UIView (but are not its child and so they should remain) are now behind it.
What might be causing this and what is the simplest way to make them appear on top (as they do whey I open main.storyboard)
EDIT
I added a line of code in the rootView of the MainNavigationController in its viewDidLoad method:
self.view.sendSubviewToBack(wholeScreenView)
and it solved the problem.
However, does anybody know why do I have to code it myself and the views are not like in the Main.storyboard?
The storyboard is not configured the way you think it is. Your wholeScreenView is in fact in front of the other views, in the storyboard. The other views (the labels and buttons) are not subviews of wholeScreenView; they are subviews of the main view, and so is wholeScreenView. It is a later subview, so it is in front of them.
I have a view controller which has a UISegmentControl with two buttons. I load this View and when the SegmentValue has changed i'll add a view controller into the view.
This is MainViewController
In the class I define the controllers
var tabNavigation: UISegmentedControl!
let viewController1:ViewController1 = ViewController1()
let viewController2:ViewController2 = ViewController2()
// Create the segment control
self.tabNavigation = UISegmentedControl(items: ["v1", "v2"])
self.tabNavigation.selectedSegmentIndex = 0
self.tabNavigation.frame = CGRectMake(60, 250, 130, 25)
self.tabNavigation.addTarget(self, action: "segmentedValueChanged", forControlEvents: .ValueChanged)
self.navigationItem.titleView = self.tabNavigation
// set first view
self.addChildViewController(viewController1)
self.view.addSubview(viewController1.view)
// Segement changed
func segmentedValueChanged() {
if (self.tabNavigation.selectedSegmentIndex == 0) {
self.addChildViewController(viewController1)
self.view.addSubview(viewController1.view)
} else {
self.addChildViewController(viewController2)
self.view.addSubview(viewController2.view)
In the storyboard i have a segue from MainViewController to ViewController3
Now in ViewController1 i'm trying to create a segue (should be part of a previous navigation controller so swipe across with a back button) from ViewController1 to ViewController3. But fails as the segue does not exist as ViewController1 is made completely from Code.
My code for the segue is below but obviously fails as that is the segue identifier for MainViewController to ViewController3
performSegueWithIdentifier("loadVC3", sender: nil)
What you're looking for is to initialize a viewController programmatically and then show it, for that you need first to set a unique Storyboard ID and then initialize it. Like this:
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController3") as! UIViewController
// and then present it modally
presentViewController(viewController, animated: true, completion: nil)
// or push it onto the navigation stack
pushViewController(viewController, animated: true)
You cannot create segues programmatically. Look at this answer:
Creating a segue programmatically
I would probably use a XIB to design all the view controllers that you create programmatically.
I am new to iOS development. I have a story board with 2 view controllers, I link them up to UIViewController classes, it works when I try load the second class from the first class (like a splash screen going into the main menu) but then the 'menu' does not load the view from the storyboard. It loads a black screen. I have assigned the class to the viewcontroller in the right hand sidebar of the storyboard and coloured the screen red to see if it loads the class, it does, but if I take the red out, it loads a black screen, not the desired screen from the storyboard.
Screen 1's (Splash)'s code:
func switchScreen() {
let secondViewController:vcMainLogin = vcMainLogin()
self.presentViewController(secondViewController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "switchScreen", userInfo: nil, repeats: false)
}
Screen 2's (login / menu)'s code:
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.redColor()
// Do any additional setup after loading the view.
}
It is loading because the colour of the screen turns red, but when I take that out it loads black, not the screen from the storyboard.
You need to instantiate the view controller from the storyboard and not create it via the initialize function. To do this you need to assign your view controller a storyboardID in interface builder (view -> utilities -> identity inspector). In this example I load a view controller with a storyboard ID of "VC2" from the storyboard named "MainStoryboard".
let mainStoryboard = UIStoryboard(name: "MainStoryboard", bundle: NSBundle.mainBundle())
let vc : UIViewController = mainStoryboard.instantiateViewControllerWithIdentifier("VC2") as UIViewController
Here is the equivalent objective-c code for reference
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"mainStoryboard" bundle:[NSBundle mainBundle]];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"VC2"];
I am not yet used to Swift. However, it looks ot me as if you load just instanticate a brand new mcMainLogin view controller instead of initializing it from a nib file or loading it from a story board. Naturally it would be empty (black).
Go back to the references or wait for somebody with Swift experience to tell you how to load the view controller from the storyboard.
If you create all your view controllers programmatically and do the navigation programatically then there is no need for storyboards at all. You'd be far better of either complying to the storyboard concept including navigation at least in 90+ % of all navigation events or work with individutal nib/xib files.