I have close to 8 view controllers , Each and every view controller has next and back button . How could I do left and right transitions here through swift code . To be more specific on tapping back , previous view controller should slide from left and on tapping next , the next view controller should slide from right.
I am pretty new to iOS development , Any help would be really appreciable.
Thanks In Advance
You should be able to do it using UIPageViewController combining it with its delegate.
However, I'm gonna shamelessly point you to my open source project of custom container with interactive transitions - InteractiveTransitioningContainer. While it aims at allowing to implement an interactive container (as an example it includes a container that allows swiping through viewControllers the way as UIPageViewController works), you can use the SwipeToSlideInteractiveTransitioningContainer class to achieve what you want:
// here you will want your 8 controllers
let vcs = [FirstViewController(), SecondViewController(), ThirdViewController()]
let container = SwipeToSlideInteractiveTransitioningContainer(with: vcs)
// this will disable swiping to navigate between containees
container.interactive = false
self.present(container, animated: true, completion: nil)
// shows the second viewController (index based from 0)
container.show(at: 1, animated: true)
// or move using previous and next convenience methods
let success = container.showNext(animated: true)
You can install it using Cocoa pods. Any feedback welcome :).
Related
Apologies as I know there are some similar questions, but I've been looking for two weeks through every one I can find, and cannot figure it out (I'm a bit of a novice).
I have a few different View Controllers, not using a Navigation Controller. I can segue between them no problem. The issue is, I need each view to be dismissed when I segue to a new one. Here is some of what I've tried so far.
Option 1 (in new View Controller)
override func viewDidAppear(_ animated: Bool) {
presentingViewController?.dismiss(animated: false, completion: nil)
}
Option 2 (in old View Controller)
override func viewDidDisappear(_ animated: Bool) {
self.dismiss(animated: false, completion: nil)
}
In both of these cases, the new view gets dismissed and I'm taken back to the old view. I've tried about 20 versions of similar code.
Should I be using the first VC in my program as my "main" view controller, and presenting/dismissing all others on top of it? I didn't think this approach seemed memory efficient, when the "main" VC is not often used after initially loading the app.
It seems like I'm missing or not understanding something. Any help would be greatly appreciated.
Think of it this way: A view controller can't exist on an island. It has to be presented on top of something.
That means when you present one VC on top of another, the presenting view controller is the "foundation" for the new one you just presented.
If you don't want to present VCs on top of each other, you have a couple of options:
1) Use a navigation controller. This is probably the best approach. You can present or push any view controller. If you decide to push, you can remove the old one from the navigation stack, or you can keep it there so the user can go back. There are lots of ways to use a navigation controller, and it's easily the most flexible way to navigate between controllers.
2) Use a tab bar controller. This works best if you have just a few different view controllers in your app, but it's good for certain use cases.
3) Do exactly what you said in your post (use the root view controller to present/dismiss all other VCs). As I said, you can't present a view controller out of thin air-- there always has to be something behind it. Unless there's a ton of stuff going on in your root VC, this shouldn't cause any memory issues. This approach should be fine unless you're very particular about the animations between your view controllers.
In general, I wouldn't worry too much about memory usage until it becomes a problem. It should be fine to present view controllers on top of each other for 99% of normal use cases.
if you want to present VC B from VC A and want to dismiss VC A while Presenting you can use this Code
let parentVC = presentingViewController
dismiss(animated: true) {
let vc = self.storyboard!.instantiateViewController(withIdentifier...)
parentVC.present(vc, animated: true)`enter code here`
} `enter code here`
I am learning ios development and am trying to make an app that has two views, each with a button that when pressed will send you to the other view. I have the two scenes set up in the storyboard and the button connected to an action. According to what I've read, using the instantiateViewController and an identifier should be enough to change the view. But when I run the simulator the first view appears but clicking the button has no effect. I dont't even get a error message.
#IBAction func SwitchViews(_ sender: UIButton) {
//Switch view controllers
let vc = storyboard?.instantiateViewController(withIdentifier: "second")
navigationController?.pushViewController(vc!, animated: true)
}
Have you embed you storyboard to navigation controller.In your code navigation controller optional so controller is not able get navigation controller.
you have to embed your first storyboard to navigation controller And it will work.You can do it by In Xcode>Editor>Embed In>Navigation Controller.
Just one suggestion if you are going to be developing apps that doesn't use navigation view what you have done is slightly off. The right way to do the connection to multiple views in a single view application is like this. I'll explain it in steps
Step 1 - Add a ViewController to your story board
Step 2 - Create a cocoa touch class from file - new - file (command + N will also do the trick)
!!! make sure its cocoa touch class !!!
Step 3 - keep subclass of as UIViewController enter the class name keep it unique to what the view does so the code looks clean and clear for everyone.
Step 4 - Hit next and finish. Now go to the story board and add the class name to the view controller you have created inside the identity inspector and add the storyboard identifier name as well
Step 5 - link your button to an action within your swift file as TouchUpInside and add the following code
#IBAction func startButtonPressed(_ sender: UIButton) {
let controllerVariable = self.storyboard?.instantiateViewController(withIdentifier: "storyboardIdentifier") as! ViewControllerClassName
self.present(controllerVariable, animated: true, completion: nil)
}
This should do the trick for creating single view applications and then building up your app with multiple screens.
But if your app uses IOS default navigation controller style like a nav bar with navigation items and a back button best practice is to use the nav controller.
If it doesn't then you have complete control over how you design your user interface by following the above steps.
Hope this helps :)
I have several views in my storyboard.
The flow of the program is a user enters start mileage in my MileageViewController (which is a standard UIViewController) and then clicks a button to select their start location from a separate view. This view is a treeviewcontroller and because of editing I had to embed in a NavigationViewController which introduced a UINavigationBar and I have an edit button. I can edit my list (and I'll eventually add adding to the list).
All is fine... until I segue from a cell in the treeview back to my MileageViewController into which I update the title from the selected cell into startLocation UIText... hope I've painted a picture you understand... :)
My problem is that on getting back to the MileageViewController it now has a header (UINavigationBar) with Back to LocationChoiceTreeViewController.... how do I disable the header in this instance?
on the viewWillAppear of the controller
if let n = navigationController {
n.setNavigationBarHidden(true, animated: false)
}
So I am working on an app and am finally getting to a point where I am starting to build actual modules instead of playgrounds and utility apps for tests. So I really want to do this right since I am jumping into the real deal right now. I was hoping to get advice that will help me accomplish my goals for the apps "flow" without me hacking something together that will come back to bite me later.
So imagine I have a home screen(a single view controller) that can branch to multiple storyboards. The mechanism I want to trigger transitions is the user grabbing an image on the home screen with their finger, and flicking it off the screen. When the image is no longer on screen, I'd like to transition to a storyboard that corresponds to that image. For instance, the user might flick the "settings" image to open a settings panel.
[home storyboard] -- [user flicks image off screen] --> [alternate storyboard]
I have already accomplished this kind of, but with the way I am doing it now I am unsure how to be able to navigate back from the second storyboard back to the home storyboard. It also seems unclean and hacky to me.
Right now it is set up as such:
Home is its own storyboard - main.storyboard
Home contains one simple viewcontroller
Alt is another storyboard - alt.storyboard
Alt contains a navigationcontroller
How can I facilitate things such that Alt's navigation controller will recognize that it was just in the Home storyboard, so that it will provide a "back" button for navigating back home?
Or, if anyone has any advice as to how I might accomplish this in a neater way, I would greatly appreciate it. I want each "module" (ie alt.storyboard's contents) to be in different storyboards for organizational sake.
Here is the code I use to seque to my second storyboard:
if !(recognizer.view!.window == nil) {
print("object left window")
let viewController: UIViewController = (self.storyboard?.instantiateViewControllerWithIdentifier("Alt"))! as UIViewController
self.presentViewController(viewController, animated: true, completion: nil)
}
Thanks so much for taking the time to check this out, let me know if I have not been clear enough.
you could put the main viewcontroller (from Home storyboard) itself into a navigation controller and simply push the initial viewcontroller from the storyboard you want to reach (in your example Alt storyboard) with a custom transition. so the viewcontrollers from all the other storyboards except of Home should not be embedded in a navigation controller!
I am trying to assign two view controllers to a Container View using the Interface Builder. I tried to do so, but whenever I try to "embed" the second view controller to my Container View, instead of adding another VC to it, it just replaces the one that was embedded already.
Ultimately, my main goal is to have a screen that has the following elements (in order, from top to bottom):
-A navigation bar
-A view of height 50 that contains a segmented controller (which will switch between tableVCs)
-A main view, which will contain my Container view
-A tabbed bar
My current setup is almost as described above. Here is a picture:
The view controller I am interested in the most is in the one with the highlighted container(HomeViewController). The approach I am currently using is hacky, because I currently have 2 container views, one on top of another, and they embed the 2 table view controllers depicted to the right (one per container).
I do not like this approach very much because both containers get instantiated whenever the main VC (Home View Controller) is instantiated, therefore making 2 network calls by default to load their content, possibly slowing down the device and maybe using more memory than needed.
Ideally, I would load the content of one table view controller that is mapped to one of the segmented controls. Then, I would have a mechanism that somehow instantiates the second table view controller whenever I go to the second button in the segmented control (and possibly deallocating/getting rid of the other VCs), and so on with the third. Or somehow be able to display/alternate between 2 or more view controllers in an area (view) inside my HomeViewController.
Currently I have this simple code that switches (hides and shows) between container views in my HomeViewController:
#IBAction func segmentChanged(sender: AnyObject) {
switch segmentedControl.selectedSegmentIndex{
case 0:
println("index1 selected")
containerView1.hidden = false
containerView2.hidden = true
break
case 1:
println("index2 selected")
containerView1.hidden = true
containerView2.hidden = false
break
default:
containerView1.hidden = false
containerView2.hidden = true
break
}
}
As I said, this only switches between the views that are loaded already in my view controller, with the data in them already.
I just wanted to see if what I am trying to code is doable, or if I am actually tackling the problem the right way, although I doubt I am doing so.
Thank you for reading my post and for your advice in advance.
Cheers!
Add embed segue to NavigationController, add ViewController as rootViewController to NavigationController, from rootViewController add as many segue as you wish. To load controller you need just override segue class to push without navigation.
class NoAnimationSegue: UIStoryboardSegue {
override func perform() {
self.sourceViewController.navigationController?.pushViewController(self.destinationViewController, animated: false)
}
}