i am using slideMenuController from github for left drawer effect.
i had implemented successfully.
but i am having one issue that from the menu i am navigate to viewController2 and viewController2 have one uibutton which push viewcontroller1.
now i am selecting viewcontroller2 from slideMenuController but it navigate to viewcontroller1 instead of viewcontroller2.
i am having navigation in appdelegate
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var mainViewController : MainViewController = storyboard.instantiateViewControllerWithIdentifier("MainViewController") as MainViewController
let leftViewController = storyboard.instantiateViewControllerWithIdentifier("LeftViewController") as LeftViewController
let rightViewController = storyboard.instantiateViewControllerWithIdentifier("RightViewController") as RightViewController
nvc = UINavigationController(rootViewController: mainViewController)
leftViewController.mainViewController = nvc
let slideMenuController = SlideMenuController(mainViewController:nvc!, leftMenuViewController: leftViewController, rightMenuViewController: rightViewController)
println("\(nvc!.viewControllers.count)")
self.window?.backgroundColor = UIColor(red: 236.0, green: 238.0, blue: 241.0, alpha: 1.0)
self.window?.rootViewController = slideMenuController
self.window?.makeKeyAndVisible()<br>
and navigation from slideMenus this kind of navigation
func changeViewController(menu: LeftMenu) {
switch menu {
case .Main:
self.slideMenuController()?.changeMainViewController(self.mainViewController, close: true)
case .Swift:
self.slideMenuController()?.changeMainViewController(self.swiftViewController, close: true)
break
case .Java:
self.slideMenuController()?.changeMainViewController(self.javaViewController, close: true)
break
case .Go:
self.slideMenuController()?.changeMainViewController(self.goViewController, close: true)
break
case .NonMenu:
self.slideMenuController()?.changeMainViewController(self.nonMenuViewController, close: true)
break
default:
break
}
}
in slideMenuController the function
public func changeMainViewController(mainViewController: UIViewController, close: Bool) {
removeViewController(self.mainViewController)
self.mainViewController = mainViewController
setUpViewController(mainContainerView, targetViewController: mainViewController)
if (close) {
closeLeft()
closeRight()
}
}
i am trying to remove also navigation stack of appdelegate and assign it again while changing the menu. but it didn't work.how can i achieve. please help me out.
Error is in your JavaViewController , correct it like this :-
class JavaViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var btn : UIButton = UIButton(frame: CGRectMake(150, 150, 60, 60))
btn.setTitle("Click", forState: UIControlState.Normal)
btn.addTarget(self, action: "btnClick:", forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(btn)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.setNavigationBarItem()
}
func btnClick(sender: UIButton) {
var storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier("MainViewController") as! MainViewController
let leftViewController = storyboard.instantiateViewControllerWithIdentifier("LeftViewController") as! LeftViewController
let nvc: UINavigationController = UINavigationController(rootViewController: mainViewController)
leftViewController.mainViewController = nvc
self.slideMenuController()?.changeMainViewController(nvc, close: true)
}
}
Related
I am presenting a navigation controller with modalPresentationStyle as overCurrentContext. After dismissing controller screen freezes.
I am presenting a FirstViewController with NAvigationController.
let firstVC = FirstViewController.controller()
let nvc = UINavigationController(rootViewController: firstVC)
nvc.modalPresentationStyle = .overCurrentContext
present(nvc, animated: true)
Then inside FirstViewController, I am passing navigationController to push SecondViewController
override func viewDidLoad() {
super.viewDidLoad()
guard let nav = navigationController else { return }
showSecondViewController(parentController: nav)
}
func showSecondViewController(parentController: UINavigationController) {
let secondVC = SecondViewController.controller()
parentController.pushViewController(secondVC, animated: true)
}
Now first I am popping SecondViewcontroller on click action from SecondViewController
navigationController?.popViewController(animated: animated)
Then with some call back I am dismissing FirstViewController and NavigationControoler (nvc)
self.controller?.dismiss(animated: true)
self.nvc?.dismiss(animated: true)
Now after dismissing as above I am facing screen freeze issue.
I need help to resolve this issue. Please help. Why screen is freezing.
Please let me know if I am missing anything here?
Thanks
Did you see any errors in the console? I'm not clear about "some call back" as you mentioned above. Can you elaborate?
I created a small project to replicate your issue. The approach below works fine in my case
ViewController is the root view controller
FirstViewController is the first controller presented on top of ViewController
SecondViewController is pushed from the first view controller after the event "ViewDidLoad" happens in FirstViewController
I also created 1 onViewControllerDissmied callback in each ViewControllers (especially FirstViewController and SecondViewController)
In ViewController - I created a touch up inside event as below
#objc func onButtonClicked() {
let firstVC = FirstViewController()
nvc = UINavigationController(rootViewController: firstVC)
guard let nvc = nvc else { return }
nvc.modalPresentationStyle = .overCurrentContext
present(nvc, animated: true)
mycontroller = firstVC
firstVC.onViewControllerDimissed = { [weak self] in
self?.mycontroller?.dismiss(animated: true)
self?.nvc?.dismiss(animated: true)
}
}
FirstViewController
class FirstViewController: UIViewController {
var label: UILabel = {
let button = UILabel()
button.translatesAutoresizingMaskIntoConstraints = false
button.text = "First View Controller"
button.textColor = .white
return button
}()
var onViewControllerDimissed: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .purple
guard let nav = navigationController else { return }
showSecondViewController(parentController: nav)
}
func showSecondViewController(parentController: UINavigationController) {
let secondVC = SecondViewController()
parentController.pushViewController(secondVC, animated: true)
secondVC.onViewControllerDimissed = { [weak self] in
self?.onViewControllerDimissed?()
}
}
}
SecondViewController
class SecondViewController: UIViewController {
var label: UILabel = {
let button = UILabel()
button.translatesAutoresizingMaskIntoConstraints = false
button.text = "Second View Controller"
return button
}()
var onViewControllerDimissed: (() -> Void)?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: view)
let pnt: CGPoint = CGPoint(x: position.x, y: position.y)
if (view.bounds.contains(pnt)) {
onScreenTouch()
}
}
}
func onScreenTouch() {
navigationController?.popViewController(animated: true)
onViewControllerDimissed?()
}
}
i created two projects to learn how the delegate method is working..
one project created WITHOUT storyboard, just via code and my delegate is working just fine.
i built the other Project WITH storyboard, which means all ViewControllers are visible in the Interfacebuilder..
i am sure the issue lays in the definition of the ViewControllers in the code file:
let homeVC = HomeViewController()
Can someone please tell what is wrong here?
import UIKit
protocol HomeViewControllerDelegate: AnyObject {
func showMenu()
}
class HomeViewController: UIViewController {
var delegate: HomeViewControllerDelegate?
override func viewDidLoad() {
title = "App"
super.viewDidLoad()
configureNaviBar()
}
func configureNaviBar() {
// Left Bar Button Item
let burgerButton = UIImage(systemName: "line.horizontal.3")
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: burgerButton, style: .plain, target: self, action: #selector(showMenu))
}
#objc func showMenu(sender: AnyObject) {
print("show Menu (home)")
// homeDelegate is nil?
delegate!.showMenu() // throws an error!
}
}
import UIKit
class MainViewController: UIViewController {
let naviVC:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NaviVC") as! NaviVC
let menuVC:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SideMenuID") as! SideMenuViewController
let homeVC = HomeViewController()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
setupContainerView()
}
func setupContainerView() {
// menu
addChild(menuVC)
self.view.addSubview(menuVC.view)
menuVC.view.frame = CGRect(x: 0, y: 0, width: 200, height: 896)
menuVC.didMove(toParent: self)
// Home
homeVC.delegate = self
addChild(naviVC)
self.view.addSubview(naviVC.view)
naviVC.view.frame = self.view.bounds
naviVC.didMove(toParent: self)
}
}
extension MainViewController: HomeViewControllerDelegate {
func showMenu() {
// does not get called
print("did tap menu")
}
}
Error:
Debug_project/HomeViewController.swift:49: Fatal error: Unexpectedly found nil while unwrapping an Optional value
i am already searching for days now, and just can't find the solution for this...
please help me out guys
I found the solution!
Tanks to Phillip Mills and all others for helping me find this..
the solution is:
change
let homeVC = HomeViewController()
to
override func viewDidLoad() {
super.viewDidLoad()
let homeVC = naviVC.viewControllers.first as! HomeViewController // working: this is it!
}
class MainViewController: UIViewController {
let naviVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NaviVC") as! NaviVC
let menuVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SideMenuID") as! SideMenuViewController
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
setupContainerView()
}
func setupContainerView() {
// menu
addChild(menuVC)
self.view.addSubview(menuVC.view)
menuVC.view.frame = CGRect(x: 0, y: 0, width: 200, height: 896)
menuVC.didMove(toParent: self)
// Home
let homeVC = naviVC.viewControllers.first as! HomeViewController // working: this is it!
homeVC.delegate = self
addChild(naviVC)
self.view.addSubview(naviVC.view)
naviVC.view.frame = self.view.bounds
naviVC.didMove(toParent: self)
}
}
extension MainViewController: HomeViewControllerDelegate {
func showMenu() {
// does not get called
print("did tap menu")
}
}
I am trying to create a rightBarButtonItem that appears throughout my app. When this barItem is clicked I want to show a modal popup using UIPopoverPresentationController. I have been able to get the button to show up on the barItem on all the views. However when i click on the button the xib takes over the entire view (including nav bar, see image below). Please see the class below:
class MyAppsNavigationController: UINavigationController, UINavigationControllerDelegate, UIPopoverPresentationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.navigationBar.barTintColor = Colors.Red01.color()
self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white]
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "Ellipsis"), style: .plain, target: self, action: #selector(displayMenu(sender:)))
}
func displayMenu(sender: UIBarButtonItem)
{
let filterVC = DropdownMenuController(nibName: "DropdownMenuController", bundle: nil)
let nav = UINavigationController(rootViewController: filterVC)
nav.modalPresentationStyle = UIModalPresentationStyle.popover
//nav.isNavigationBarHidden = true
nav.preferredContentSize = CGSize(width: 200, height: 300)
let popover = nav.popoverPresentationController! as UIPopoverPresentationController
popover.permittedArrowDirections = .up
popover.delegate = self
popover.barButtonItem = self.navigationItem.rightBarButtonItem
popover.sourceView = self.view;
var frame:CGRect = (sender.value(forKey: "view")! as AnyObject).frame
frame.origin.y = frame.origin.y+20
popover.sourceRect = frame
popover.delegate = self
self.present(nav, animated: true, completion: nil)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
Result when clicked on the button:
When clicked the popup takes over entire view:
Any chance you're not using the right delegate method? I think this looks better:
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
Also, in this case sourceView and sourceRect is not needed: specifying a barButtonItem for the popover presentation controller is sufficient.
https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller/1622314-barbuttonitem
I want to open a specific ViewController from the TabBarController whenever a local notification is fired and their custom action is performed. I have used following line of code:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
switch response.actionIdentifier {
case "first":
DispatchQueue.main.async(execute: {
self.first()
})
case "second":
DispatchQueue.main.async(execute: {
self.second()
})
default:
break
}
completionHandler()
}
So it's a first() function:
func first() {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "Root") as! UITabBarController
let navigationController = storyboard.instantiateViewController(withIdentifier: "First") as! UINavigationController
tabBarController.present(navigationController, animated: true) {
}
self.window = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.tintColor = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0)
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()
}
Second function: second()
func second() {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "Root") as! UITabBarController
let navigationController = storyboard.instantiateViewController(withIdentifier: "Second") as! UINavigationController
tabBarController.present(navigationController, animated: true) {
}
self.window = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.tintColor = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0)
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()
}
And it's works well, but I cannot open the second ViewController while the first one is presented and the second notification is fired: In the console: Warning attempt to present ViewController...
Use this:
tabBarController.selectedIndex = 1
Or this:
tabBarController.selectedViewController = tabBarController.viewControllers![1]
Where 1 can be any of the viewcontrollers presented by your tabBarController
I had run into a similar issue and changing the selectedIndex did not work for me. Depending on the requirements of your project you can instantiate your ViewController and add it as a Subview and move to that Subview. When youre done make sure to remove that Subview.
let replyView = self.storyboard?.instantiateViewControllerWithIdentifier("replyView")
self.addChildViewController(replyView!)
self.view.addSubview(replyView!.view)
replyView!.didMoveToParentViewController(self)
I have navigation controller with one rootViewController called "LoginController". When I try to add rightBarButtonItem from init of LoginController so it works, but directly in navigation controller same operation does not works.
This works:
class LoginController: UIViewController {
init(){
super.init(nibName: nil, bundle: nil)
let button = UIBarButtonItem()
button.title = "Test2"
navigationItem.rightBarButtonItem = button
}
......
}
This doesn't work:
class MainNavigationController : UINavigationController{
private var _distributionProvider : DistributionProvider!
init(rootViewController: UIViewController, distributionProvider : DistributionProvider) {
_distributionProvider = distributionProvider
super.init(rootViewController: rootViewController)
navigationBar.barTintColor = UIColor(red: 90/255, green: 177/255, blue: 225/255, alpha: 1)
let button = UIBarButtonItem()
button.title = "Test"
navigationItem.rightBarButtonItem = button
}
....
}
Where is problem? Thanks
You've to do this:
class MainNavigationController: UITabBarController, UITabBarControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
override func viewWillAppear(animated: Bool) {
let item1 = Item1ViewController()
let icon1 = UITabBarItem(title: "Title", image: UIImage(named: "someImage.png"), selectedImage: UIImage(named: "otherImage.png"))
item1.tabBarItem = icon1
let controllers = [item1] //array of the root view controllers displayed by the tab bar interface
self.viewControllers = controllers
}
//Delegate methods
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
print("Should select viewController: \(viewController.title) ?")
return true;
}
}