I need your help.
I'm developing a app without Storyboard (using xib), in my project I have two views controllers.
In the main view (after a login) I need to put a button on top of the view to open a left side menu.
This is how I call the MainView on LoginViewController
#IBAction func logar(){
let vc = MainViewController(nibName: "MainViewController", bundle: nil)
self.navigationController!.pushViewController(vc, animated: true)
}
I imported SWRevealViewController, and this is my MainViewController:
import UIKit
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//hide BackButton
self.navigationItem.hidesBackButton = true
//image
var image = UIImage(named: "menuBtn")
image = image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
//lefBarButonItem
let newBackButton = UIBarButtonItem(image: image, style: .Plain, target: self, action: #selector(MainViewController.openMenu))
self.navigationItem.leftBarButtonItem = newBackButton;
}
func openMenu(){
let frontViewController = LeftMenuTableViewController()
let rearViewController = MainViewController()
//create instance of swRevealVC based on front and rear VC
let swRevealVC = SWRevealViewController(rearViewController: rearViewController, frontViewController: frontViewController);
swRevealVC.toggleAnimationType = SWRevealToggleAnimationType.EaseOut;
swRevealVC.toggleAnimationDuration = 0.30;
//set swRevealVC as rootVC of windows
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController = swRevealVC
}
}
When I press the button the LeftMenu occupy all the view, not like a partial view.
Any help would be appreciated. Thank you!
Related
I am failing to understand the fundamentals of what is needed to add my HomeViewController (UIViewController) as one of the tabs in my homeTabBarController (UITabBarController) using the setViewControllers method.
I have tried initializing this and simply adding it as a param in the method. There seems to be a difference between a view controller created via storyboard and one created programmatically because when I tried adding a viewcontroller:UIViewController programmatically to the setViewControllers method, it worked fine.
My code below compiles however I get a runtime exception Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ff7b8491598) at the line when homeTabBarController.setViewControllers is called
`
func loadTabBar() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let homeViewController = storyboard.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
homeViewController!.title = "Home"
homeTabBarController.setViewControllers([homeViewController!], animated: false)
homeTabBarController.modalPresentationStyle = .fullScreen
present(homeTabBarController, animated: true)
}
`
//MARK: - Create the instances of ViewControllers
let grayViewController = HomeViewController()
let blueViewController = FirstViewController()
let brownViewController = SecondViewController()
override func viewDidLoad() {
super.viewDidLoad()
//set title of the viewcontrollers
grayViewController.title = "home"
blueViewController.title = "first"
brownViewController.title = "second"
//Assigne the viewcontrollers to the TabBarViewController
self.setViewControllers([ grayViewController, blueViewController, brownViewController], animated: false)
//set system images to each tabBars
guard let items = self.tabBar.items else {
return
}
let images = ["house.fill", "star.fill", "bell.fill"]
for i in 0...2 {
items[i].image = UIImage(systemName: images[i])
}
self.tabBar.tintColor = .black
}
// You can download the project from the below github link
https://github.com/ahmetbostanciklioglu/AddingTabBarControllerProgrammatically.git
I have created a navigation controller. I added a plus button to the top right of the navigation controller which opens up a new view controller. However, I want the navigation bar to show up on the new screen as well. But it's not showing. What am I doing wrong, or what am I missing? Here is my code:
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var toDoListTextView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Setting the Title for the nav bar
title = "To Do List"
configureNavigationItems()
}
private func configureNavigationItems(){
/* Adding a button on the top right of the screen
* in the navigation bar/controller.
*/
navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(didTapPlus)
)
}
#objc func didTapPlus(){
let vc = storyboard?.instantiateViewController(identifier: "makeTask") as! makeTaskViewController
vc.modalPresentationStyle = .fullScreen
vc.title = "Create a Task"
vc.view.backgroundColor = .black
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "Back",
style: .done,
target: self,
action: nil)
present(vc, animated: true)
}
}
Storyboard
Click Here To See Picture
Demo of App
enter image description here
Each modally-presented view controller gets a brand-new view hierarchy. This means that if you want your MakeTaskViewController to have a navigation bar, you'll need to manually add a navigation controller.
class ViewController: UIViewController {
// ... your code ...
#objc func didTapPlus() {
let vc = storyboard?.instantiateViewController(identifier: "makeTask") as! MakeTaskViewController
vc.modalPresentationStyle = .fullScreen
vc.title = "Create a Task"
vc.view.backgroundColor = .black
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "Back",
style: .done,
target: vc, /// make sure to set `target` as the new view controller
action: #selector(vc.dismissMe))
/// wrap the new view controller in a navigation controller (this adds the top bar)
let navigationController = UINavigationController(rootViewController: vc)
/// so you can actually see the `Create a Task` text,
navigationController.navigationBar.barStyle = .black
present(navigationController, animated: true)
}
}
/// side note: `MakeTaskViewController` and other classes should be Capitalized
class MakeTaskViewController: UIViewController {
#objc func dismissMe() {
self.dismiss(animated: true)
}
}
Result:
Try this!
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var toDoListTextView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Setting the Title for the nav bar
title = "To Do List"
configureNavigationItems()
}
private func configureNavigationItems(){
navigationItem.rightBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(didTapPlus)
)
}
#objc func didTapPlus(){
let vc = storyboard?.instantiateViewController(identifier: "makeTask") as! makeTaskViewController
vc.modalPresentationStyle = .fullScreen
vc.title = "Create a Task"
vc.view.backgroundColor = .black
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "Back",
style: .done,
target: self,
action: nil)
navigationController?.pushViewController(vc, animated: true)
//present(vc, animated: true)
}
}
😊
I want to present SecondVC from FirstVC and make SecondVC have a rightBarButtonItem called Close which calls an #objc function which dismisses SecondVC.
Also, I want to change secondVC's title from firstVC:
This is how I present SecondVC from the FirstVC:
let secondVC = AdviceDetailsViewController()
secondVC.modalPresentationStyle = .fullScreen
secondVC.title = "Example" //Value of type 'UINavigationController' has no member 'myTitle'
self.present(secondVC, animated: true)
Code for navigationBar in secondVC:
public var myTitle: String = ""
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
self.title = myTitle
self.navigationController?.navigationBar.barTintColor = UIColor.orange
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(closeDetails))
}
#objc func closeDetails() {
self.dismiss(animated: true, completion: nil)
}
No Navigation bar is visible in secondVC, the only visible thing is gray background color.
What should I change? I am doing everything programmatically in this app.
Use this method to show second VC
let nc = UINavigationController(rootViewController: AdviceDetailsViewController())
nc.modalPresentationStyle = . fullScreen
self.present(nc, animated: true)
Regarding your Title issue,
Value of type 'UINavigationController' has no member 'myTitle' Yes its true, because we define myTitle variable on SecondVC,So we assign myTitle like this
let vc = SecondViewController()
vc.myTitle = "My Title"
let nc = UINavigationController(rootViewController: vc)
nc.modalPresentationStyle = . fullScreen
self.present(nc, animated: true)
I am working on application where after registration process home screen will appear. And the SWRevealViewController has been configure in home screen.
I want to configure SWRevealViewController programmatically.
Below is my code
let storyboard = UIStoryboard(name: "MainSW", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("HomeViewController") as! HomeViewController
let rvc:SWRevealViewController = self.revealViewController() as SWRevealViewController
rvc.pushFrontViewController(vc, animated: true)
But it gives me error like below.
Could not cast value of type 'UINavigationController' (0x110d9f860) to
'SWRevealViewController' (0x10dc346b8).
I have tried below link also
SWRevealViewController solution
But it also doesn't help me.
Here is how I have configured it :
I have created 2 UIBarButtonItem as properties of the HomeViewController (I will set them in code)
let leftButton = UIBarButtonItem()
let rightButton = UIBarButtonItem()
In viewDidLoad method:
revealViewController().delegate = self
In viewWillAppear method:
if (revealViewController() != nil) {
revealViewController().rearViewRevealWidth = -50
revealViewController().rightViewRevealWidth = -50
leftButton.image = UIImage(named: "yourImageName")! // check that the image exists, don't use !
leftButton.style = .plain
leftButton.target = revealViewController()
leftButton.action = #selector(SWRevealViewController.revealToggle(_:))
rightButton.image = UIImage(named: "yourImageName")! // check that the image exists, don't use !
rightButton.style = .plain
rightButton.target = revealViewController()
rightButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))
view.addGestureRecognizer(revealViewController().panGestureRecognizer())
view.addGestureRecognizer(revealViewController().tapGestureRecognizer())
}
This is all the code I use to set up SWRevealViewController in my HomeViewController in order to have left and right menu.
You can now use the delegate method to customize the behavior as it pleases you :
extension HomeViewController: SWRevealViewControllerDelegate {
func revealController(_ revealController: SWRevealViewController!, willMoveTo position: FrontViewPosition) {
view.alpha = position == FrontViewPosition.left ? 1.0 : 0.6
}
}
I have set an alpha on the HomeViewController to make it darker when it's not in front.
For the Storyboard part :
Create an UIViewController in the Storyboard.
Change its class to SWRevealViewController
Create 2 more UIViewControllers (1 for the left menu, 1 for the right menu. If you want only 1 menu, apply for either left or right, as you want)
Link the SWRevealViewController to the 2 UIViewControllers with segues (rear and right segues)
Link the SWRevealViewController to your UINavigationController with the front segue.
Link the UINavigationController with your HomeViewController (with root relationship)
Keep in mind that you may also want to create a custom segue for the transition between your RegisterViewController and the HomeViewController.
You can create it programmatically too:
class RegisterToHomeSegue: UIStoryboardSegue {
override func perform() {
let source = self.source as! RegisterViewController
let homeVC = self.destination as! HomeViewController
let window = source.view.window
window?.rootViewController = homeVC
window?.addSubview(source.view)
UIView.transition(from: source.view, to: homeVC.view, duration: 0.50, options: .transitionCrossDissolve, completion: nil)
}
}
And in the Storyboard change the class segue from your RegisterViewController to the SWRevealViewController to this new one RegisterToHomeSegue and give it an identifier. So that in the RegisterViewController you can call :
performSegue(withIdentifier: "yourIdentifier", sender: nil)
And voilà , you now have :
Nice transition between your RegisterViewController and your HomeViewController
Your SWRevealController setup properly, with its left and right menu
Left and Right button item with tap gesture to open the corresponding menu
Change alpha on your HomeViewController when it is open
Tell me if it is helping you.
I implemented SWRevealController with storyboard and everything works great, but now I would like to program the app without storyboard.
Can someone help me with the implementation? I have a FrontViewController and a MenuViewController. Do I need an extra SWRevealViewController for this and if yes, what do I have to code?
I know there is some information on SWRevealController but it is in Objective-C and I have some problems to write this in Swift 2.0.
You can do it as follow.
Create one function createSlidingMenu in appDelegate.
func createSlidingMenu(){
let frontViewController = //create instance of frontVC
let rearViewController = //create instance of rearVC(menuVC)
//create instance of swRevealVC based on front and rear VC
let swRevealVC = SWRevealViewController(rearViewController: rearViewController, frontViewController: frontViewController);
swRevealVC.toggleAnimationType = SWRevealToggleAnimationType.EaseOut;
swRevealVC.toggleAnimationDuration = 0.30;
//set swRevealVC as rootVC of windows
self.window?.rootViewController = swRevealVC!;
}
call createSlidingMenu in application:didFinishLaunchingWithOptions: and you are good to go.
This worked for me (in swift 3.1)
In the StoryBoard create MasterViewController, HomeViewController (embedded in UINavigationController) with storyboardId "HomeViewController", and MenuViewController (embedded in UINavigationController) with storyboardId "MenuViewController".
Create MasterViewController class and associate to UIViewController (MasterViewController) in Storyboard and implements SWRevealViewControllerDelegate protocol (see code)
import UIKit
class MasterViewController: UIViewController, SWRevealViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let frontNavigationController:UINavigationController
let rearNavigationController:UINavigationController
let revealController = SWRevealViewController()
var mainRevealController = SWRevealViewController()
let menuTable = self.storyboard?.instantiateViewController(withIdentifier: "MenuViewController")as! MenuViewController
let homepage = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
frontNavigationController = UINavigationController(rootViewController: homepage)
rearNavigationController = UINavigationController(rootViewController: menuTable)
rearNavigationController.setNavigationBarHidden(true, animated: false)
revealController.frontViewController = frontNavigationController
revealController.rearViewController = rearNavigationController
revealController.delegate = self
mainRevealController = revealController
UIApplication.shared.delegate!.window?.rootViewController = mainRevealController
}
}
As alternative you could omit MasterViewController and:
implement SWRevealViewControllerDelegate in AppDelegate and
copy the code of viewDidLoad body wrote above in application:didFinishLaunchingWithOptions:
In addition to Hitendra, I modify the following code so I can put navigation in Home
AppDelegate.swift
func toHome() {
let frontViewController = HomeController()//create instance of frontVC
let rearViewController = MenuController() //create instance of rearVC(menuVC)
let swRevealVC = SWRevealViewController(rearViewController: rearViewController, frontViewController: frontViewController);
swRevealVC?.toggleAnimationType = SWRevealToggleAnimationType.easeOut;
swRevealVC?.toggleAnimationDuration = 0.30;
navigationController = UINavigationController(rootViewController: swRevealVC!)
self.window?.rootViewController = navigationController
}
LoginController.swift, when user click login button
#objc private func login() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.toHome()
return
}
HomeController.swift
override func viewDidLoad() {
super.viewDidLoad()
setupLayout() // layout programmatically, I didn't put code here
let menuButton = UIBarButtonItem(title: "Menu", style: .plain, target: self, action: #selector(HomeController.menu))
self.revealViewController().navigationItem.leftBarButtonItem = menuButton
}
#objc private func menu() {
revealViewController().revealToggle(self)
}