Opening a side menu on click on a TAB bar in SWIFT - swift

I want to make something like below snapshots.
When I click on profile tab bar instead of opening a new view controller it shows a side menu. Is it something that has been handled on click of tabbar ?

if you want to achieve something like your screenShot then you are using a wrong library, because when you show your right viewController the front viewController go to left by amount of width of your right viewController, but anyways here is the code for what you need to do
first you need to put your viewController as delegate of your TabBarViewController and in func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool you need to return false and call the method of SWRevealViewController to show right viewController rightRevealToggleAnimated(true)
class FirstViewController: UIViewController,SWRevealViewControllerDelegate,UITabBarControllerDelegate {
#IBOutlet weak var sliderControl: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.revealViewController().delegate = self
self.tabBarController?.delegate = self
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
//self.view.removeGestureRecognizer(self.revealViewController().panGestureRecognizer())
//self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
//checking for specific viewController
if(viewController is DesiredViewControllerClass) {
self.revealViewController().rightRevealToggleAnimated(true)
}
return false
}
}
I hope this helps you, regards

You can use the tab bar delegate:
extension ViewController: UITabBarDelegate {
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
// Present hamburger menu
}
}

Related

Button title set only for the second tab

In my project there is a Segue Show(e.g. Push). After clicking the mainButton, TabBarController is presented. When I choose the second tab, the method setButtonsTitle is called and when I swipe the TabBarController down, I can see "item 2" instead of the "Button" title (default title). But when I click the first tab afterwards and swipe the TabBarController down, it remains "Button". My first thought was that the method does not get called, but this is not true (checked in debugger). Also, print(title) shows "Item 1".
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mainButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! TabBarController
destination.selectionDelegate = self
}
}
extension ViewController : ButtonThings {
func setButtonsTitle(title: String){
mainButton.titleLabel?.text = title
print(title)
}
}
And the TabBarController:
import UIKit
class TabBarController: UITabBarController {
weak var selectionDelegate: ButtonThings?
override func viewDidLoad() {
super.viewDidLoad()
}
//MARK: UITabBarController
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
selectionDelegate?.setButtonsTitle(title: item.title ?? "no title")
}
}
protocol ButtonThings : class {
func setButtonsTitle(title: String)
}
I was able to reproduce that issue that you had mentioned. I then set the button type to custom and the button title started showing correctly.
Hope this helps.

UITabBar item did select is not calling in swift 5

I have used tabbar in swift 5 . But when i click in tabbar item, tabbar didselect item not calling.But I did not used TabbarViewController. I have used bellow code in my viewController..
class ViewController: UIViewController,UITabBarDelegate {
#IBOutlet weak var bottomTab: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
bottomTab.delegate = self
}
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
print("Selected item")
}
}
Please help me to calling didSelectItem from viewController
1) In your ViewController inherit UITabBarControllerDelegate
2) Set delegate in a viewDidLoad
3) Add a function
Example:
class ViewController: UIViewController, UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let tabBarIndex = tabBarController.selectedIndex
if tabBarIndex == 0 {
//do your stuff
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
}
}
I believe you are implementing the incorrect method. Try implementing this method instead:
func tabBar(UITabBar, didSelect: UITabBarItem)
Sent to the delegate when the user selects a tab bar item.
Source

Button in view doesn't work from view container

I have a view container in my view controller, which is stretched to whole screen. User interaction enabled is on. When I open another view via this view container in this view controller, button is clickable but doesn't respond. What should I do to make it work?
ViewController:
class ViewController: UIViewController {
#IBOutlet weak var viewContainer: UIView!
var views: [UIView]!
override func viewDidLoad() {
super.viewDidLoad()
views = [UIView]()
views.append(LoginVC().view)
views.append(RegisterVC().view)
for v in views{
viewContainer.addSubview(v)
}
viewContainer.bringSubview(toFront: views[1])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func switchViewAction(_ sender: UISegmentedControl) {
print("clicked - segment")
self.viewContainer.bringSubview(toFront: views[sender.selectedSegmentIndex])
}
and this is the button in the another view
#IBAction func registerTapped(_ sender: UIButton) {
print("Clicked - register")
}
I used Managing View Controllers tutorial to make it working.
You have to replace the entire ViewController, not just the View.
#IBAction func switchViewAction(_ sender: UISegmentedControl) {
self.viewContainer.bringSubview(toFront: views[sender.selectedSegmentIndex])
}
Your current code is just replacing LoginVC's view with RegisterVC's view, instead of replacing LoginVC with RegisterVC. When you do that, you leave behind the ViewController in charge of actually responding to any interaction.
You'll have to rework your code to keep track of the ViewControllers instead of just their views. Then, instead of adding all of your views to viewContainer and moving them to the front when you need to change the current view, you should set the your child ViewController (the ViewController embedded in your container) to the ViewController you want to show (either LoginVC or RegisterVC).

interactivePopGestureRecognizer corrupts navigation stack on root view controller

In my UINavigationController I added custom back buttons with the side effect that it is not possible anymore to swipe left to right to pop the view controller and navigate back.
So I implemented interactivePopGestureRecognizer in my custom UINavigationController class:
class UINavigationControllerExtended: UINavigationController, UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if self.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
self.interactivePopGestureRecognizer?.delegate = self
}
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return gestureRecognizer.isKindOfClass(UIScreenEdgePanGestureRecognizer)
}
}
This works fine except when I am in my root view controller (RVC) which is a UICollectionViewController, i.e. the most bottom view controller in the navigation stack. When I do the swipe left to right gesture, nothing seems to happen, as expected. But when I then tap a UICollectionViewCell the destination view controller (DVC) does not get pushed over the RVC. Instead I only see the DVC's shadow on the right side of the screen.
The RVC is not responsive anymore, but as I swipe left to right again, the DVC interactively moves right to left into the screen. When I finish the gesture, the DVC moves completely into the screen just to quickly disappear left to right again. The RVC becomes responsive again.
So it seems the DVC gets pushed onto the navigation stack but not visibly into the screen.
Any suggestions where this strange behaviour originates?
Implement UINavigationControllerDelegate for your navigation controller and enable/disable the gesture recognizer there.
// Fix bug when pop gesture is enabled for the root controller
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = self.viewControllers.count > 1
}
Keeping the code independent from the pushed view controllers.
My current solution is to disable the interactivePopGestureRecognizer in the root view controller:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.interactivePopGestureRecognizer?.enabled = false
}
In the first child view controller I enable it again. But this seems to be more a workaround because I don't understand the actual problem why the navigation stack got messed up in the first place.
Here is my solution for this. Swift 4.2
Implement UIGestureRecognizerDelegate and UINavigationControllerDelegate protocols. In my case I did this in an UITabBarController that would be also my root view controller.
Then, on viewDidLoad, do:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.interactivePopGestureRecognizer?.delegate = self
self.navigationController?.delegate = self
}
Then, add the delegate method for UINavigationControllerDelegate and check if it is the root view by counting the number of view on the navigation controller and disable it if it is or enable it if its not.
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
let enable = self.navigationController?.viewControllers.count ?? 0 > 1
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = enable
}
Lastly, add the UIGestureRecognizerDelegate method
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
This should fix the problem without the necessity of manually enabling/disabling the gesture recogniser in every view of your project.
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.isEnabled = self.viewControllers.count > 1
}
Updated #rivera solution for Swift 5
Solution from Guilherme Carvalho worked for me, but I had to assign delegate methods in viewWillAppear, in viewDidLoad was too late for my implementation.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.interactivePopGestureRecognizer?.delegate = self
navigationController?.delegate = self
}
Try this code
func navigationController(navigationController: UINavigationController, didShowViewController vc: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = self.vc.count > 1
}

Popovers in Storyboard, how to handle the delegate

In a storyboard i have a view controller which has a segue to another viewcontroller, with the "Present As Popover" applied. If i don't add any code, this works as id expect.
Issue:
I need to get the delegate working so i can get data back from the popover. I have created the delegate in the popover.
I have added
class LoginView: UIViewController,UIPopoverPresentationControllerDelegate, UIPopoverControllerDelegate,KeypadDelegate
I have added the functions to my main view controller.
Issue i have is how to set the delegate on the segue.
i have tried
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "KeyPadLoad"
{
let popoverViewController = segue.destinationViewController as! UIViewController
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
popoverViewController.popoverPresentationController!.delegate = self
}
}
The segue is defiantly called KeyPadLoad but when the delegate functions should be called in the popover nothing happens.
What am i doing wrong
Thanks
You have to implement the UIPopoverPresentationControllerDelegate in the class that presents the Popover. The methods of the UIPopoverPresentationControllerDelegate protocol let you customize the behavior of a popover-based presentation.
If you have set a segue to go to the Popover and you set the segue as Present as Popover then your class has to be like this :
class ViewController: UIViewController, UIPopoverPresentationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var popOver = segue.destinationViewController as! PopOverViewController
popOver.popoverPresentationController!.delegate = self
}
// Tells the delegate that the popover was dismissed.
func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
println("dismissed")
}
}
Where the class PopOverViewController is just an UIViewController that handle the Popover, no more, something like this code :
class PopOverViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
With the above code you should see the message:
dismissed
Every time that the PopOverViewController is dismissed.
I hope this help you.