Can i make custom UITabBarController with custom event tap on TabBarItem? - ios

I need to display the UITabBarController, but I don't need it to switch me to the Controller from the viewControllers array. Can I reassign the event or would it be better to create my own such TabBarController?

You can create a subclass for UITabBarController and confirm to UITabBarControllerDelegate
Then you can perform custom tab section actions in shouldSelect method.
func tabBarController(_ tabBarController: UITabBarController,
shouldSelect viewController: UIViewController) -> Bool
{
if viewController == secondViewController {
//Do your actions
return false
}
return true
}

Related

Show a ViewController that is not in UITabBarController's viewControllers list

I have a UITabBarController and i'm setting some ViewControllers to its viewControllers list like below
let tabBar = UITabBarController();
tabBar.viewControllers = vcs;
When view is loaded, the firs ViewController in vcs list will be shown.
What i want is, showing a UIViewController that is not in vcs list (and none of tabBar must be selected).
I want to show this UIViewController only when view is loaded for the first time. After that the user tapped one of the tabBarItems, i want to load the associated ViewController.
So my problem is 'Showing a UIViewController' that is not in vcs list
Look at UITabBarControllerDelegate method tabBarController(_:shouldSelect:).
Make yourself delegate of your UITabBarController, depending if you use Storyboard or not, it might be easier to create a custom class that inherit from UITabBarController be itself delegate and set that class into Storyboard.
var hasNotShownYet = false
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
guard hasNotShownYet else { return true /* Allow selection as "normal" */ }
presentCustomVCModally()
hasNotShowYet = true
return false
}

Catch UITaBbarViewController item selection to make decision of showing it

I need to catch UITabBarController item selection for the case when user taps on camera item and app requests permissions and if permissions not granted then not show Camera VC. Is it possible?
Implement
func tabBarController(_ tabBarController: UITabBarController,
shouldSelect viewController: UIViewController) -> Bool {
if viewController is YourVC {
}
else {}
}
And conform to UITabBarControllerDelegate

Swift: Problems with custom UIView.transition?

Ok, I have looked through https://developer.apple.com/videos/play/wwdc2013/218/ and SO questions similarly trying to make custom transitions with a tab bar controller and its viewcontrollers but Im running into confusion after figuring out the main steps here.
I need to know how (meaning example code would be really helpful) to call a custom UIView.transition OR just have a custom option in UIView.transition. I need to use this to make a sliding/modal -mimicking transition between tabs in my tab bar controller.
The only way I can get a transition to happen is using the below function (this makes them dissolve):
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if selectedViewController == nil || viewController == selectedViewController {
return false
}
let fromView = selectedViewController!.view
let toView = viewController.view
UIView.transition(from: fromView!, to: toView!, duration: 0.3, options: [.transitionCrossDissolve], completion: nil)
return true
}
And calling it manually here where I programmatically chnage the *selectedIndex* for my tab controller:
//SWITCHES BUTTON -------------------------------------------
func switchTab(index: Int)
{
//transition
self.tabBarController(self, shouldSelect: (viewControllers?[index])!)
I have read about and tried making a custom class UIViewControllerAnimatedTransitioning but don't know how this would fit in programmatically here -
my attempts passing my tab bar controller and the toView and fromViewinto the custom class result in nothing happening/animating. That is why Ive resorted to UIView.transition here.
How can I make a custom UIView.transition? What can I do here?
You should conform to UITabBarControllerDelegate
and Create a customTransition class and pass it as follows:
func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let animator = TabAnimationManager()
return animator
}
And Class TabAnimationManager should be a subclass of UIPercentDrivenInteractiveTransition and conform UIViewControllerAnimatedTransitioning protocol. You can add your custom animations in that class.

Dismiss View Controller inside UITabController

I've a project which contains a tab controller, as the main 'page'.
I want to add a UITabBar button item, which presents a view controller modaly, and within that view controller, add a dismiss button that dismisses that view controller and returns to the previous tab selection.
To clarify, it's something that the Medium app for iOS uses, when you click on the create post item, it presents it modaly and dismisses it when you want to.
I can present the view controller, but I can't dismiss it.
Hope I made myself understandable.
Example:
So I've managed to solve this as I wanted to, hope the answer will help someone in the future.
First of all, I set on my first loaded view controller, lets say my 'Home' view controller the tabBarController delegate to be my AppDelegate.swift file (this is personal preference), as:
self.tabBarController?.delegate = UIApplication.shared.delegate as? UITabBarControllerDelegate
Then in my AppDelegate.swift file i added to the class properties the delegate UITabBarControllerDelegate so I could access the tabBarController delegate functions, such as
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {}
Then edited the function to interact with my specific view controller.
The final version of the function:
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if viewController is ViewControllerToPresentModaly {
if let newVC = tabBarController.storyboard?.instantiateViewController(withIdentifier: "modalVC") {
tabBarController.present(newVC, animated: true)
return false
}
}
return true
}
Here if you want the regular tab behaviour, return true or your own return false
;)

How to pop to root after double tapping a tab bar item?

Normally when a UINavigationController is placed in a UITabBarController the navigation controller pops to root with the respective tab it is in is double tapped. How do I achieve the same effect with a UISplitViewController is between the tab bar controller and the navigation controller? Ideally it would recurse through the view controller's child view controllers and calling popToRootViewController on all navigation controllers that it finds. Do I have to add my own gesture recognizer to the tab bar since it doesn't look like there is a hook for knowing when a user has double tapped a tab?
In Swift 4, it can go something like this:
class TabBarViewController: UITabBarController, UITabBarControllerDelegate {
private var shouldSelectIndex = -1
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
shouldSelectIndex = tabBarController.selectedIndex
return true
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if shouldSelectIndex == tabBarController.selectedIndex {
if let splitViewController = viewController as? UISplitViewController {
if let navController = splitViewController.viewControllers[0] as? UINavigationController {
navController.popToRootViewController(animated: true)
}
}
}
}
}
Instead of setting up a UIGestureRecognizer I simply keep track of the selected index in shouldSelectViewController and popped to root on my master navigation controller in didSelectViewController if the old selected index was the same as the new one.

Resources