I Embedded a ViewController in a UINavigationController and after that, I added a new ViewController and connected it with a segue to the first ViewController that is embedded in a UINavigationController. then I wanted to add a BarButtonItem to that second view, but when I let go the bar button item in the top of the view next to the title, it inserts it at the button, and when I run the app it only shows the back button to the first screen and the title. (see the picture of how it looks when running and how it looks after inserting it at the top)
I hope you understood the question and you can help me!
thanks in advance!
Benji
write this code in your viewDidLoad Method of controller where you want to add button
let navBtn = UIButton(type: .custom)
navBtn.setImage(UIImage(named: "side_drawer"), for: .normal)
navBtn.frame = CGRect(x: 0, y: 0, width: 40, height: 100)
navBtn.addTarget(self, action: #selector(openMessagingThread(_:)), for: .touchUpInside)
let rightNavBarItem = UIBarButtonItem(customView: navBtn)
self.navigationItem.setRightBarButton(rightNavBarItem, animated: true)
//Action for barButton
#objc
func openMessagingThread(_ sender: UIButton) {
}
Related
I am using SecondView programmatically. I click the button in ViewController to open SecondView controller, but now I want to back to ViewController from SecondView. I do not have storyboard in SecondView and I want to click the closeButton to go back to ViewController. My code work but when I click the close button it does not work. Any idea?
import UIKit
class SecondView: UIViewController {
var closeButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
closeButton.addTarget(self, action: #selector(dismissActionSheet), for: .touchUpInside)
}
#objc func dismissActionSheet() {
self.navigationController?.popViewController(animated: true)
}
}
You are instantiating a new UIButton, adding a target, but never adding the button to the UI. If you are seeing a button in your UI, it must be one that you added in Interface Builder, not the one you reference here. I suspect your intent was not:
var closeButton = UIButton()
but rather:
#IBOutlet var closeButton: UIButton!
… and hook that button’s outlet in IB.
Or better, rather than adding a target in viewDidLoad, hook up an #IBAction for the button directly in IB:
#IBAction func didTapButton(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
You don't appear to need the closeButton outlet (at least for what you have shared with us thus far).
By the way, popViewController only works if this is embedded in a navigation controller. If you are not using a navigation controller (i.e., you “presented” the view controller rather than “pushing” one), the navigationController will be nil (and navigationController?.popViewController will do nothing). If not using navigation controller, call dismiss rather than popViewController.
If you have created the Second view programmatically:
Why not set a frame to the button and add it to self.view?
eg:
let button = UIButton(frame: CGRect(x: 50, y: 100, width: 80, height: 40))
button.setTitle("Pop VC", for: .normal)
button.addTarget(self, action: #selector(btnTouched), for: .touchUpInside)
self.view.addSubview(button)
then try to pop back:
func btnTouched(sender: UIButton!) {
if let navController = self.navigationController {
navController.popViewController(animated: true)
}
}
I have a turbolinks-ios app that I've inherited and need to add a native nav.
At first I used the storyboard to embed the main application controller within a navigation controller, but turbolinks has it's own navigation bar so that creates two stacked navigation bars. I then deleted the nav controller from the storyboard, but now I cannot add my button to the default turbolinks nav bar. There's no errors, and if I step through the code it hits every line within my function, but nothing is displayed in the bar. What am I doing wrong?
My function which is called from viewDidLoad() within the UINavigationController class is as follows...
func addSlideMenuButton() {
let callback = #selector(toggleNav)
let btnShowMenu = UIButton(type: UIButtonType.system)
btnShowMenu.setImage(self.defaultMenuImage(), for: UIControlState())
btnShowMenu.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btnShowMenu.addTarget(self, action: callback, for: UIControlEvents.touchUpInside)
let customBarItem = UIBarButtonItem(customView: btnShowMenu)
navigationController?.navigationItem.rightBarButtonItem = customBarItem
}
Any nudge in the right direction would be greatly appreciated.
You have to call sizeToFit on the customView first.
So add btnShowMenu.sizeToFit just before creating the UIBarButtonItem.
I'm developing an iOS app with swift in which I have a TabBarController with 5 tab bar items. All of them points to a navigation controller and then to a view controller. One of them I want to show a view controller without the tab bar and when the user press cancel it should go back to the previous tab bar item/view that was selected (previously - sorry for the redundancy). They are all linked/referenced by a "Relationship "view controllers" to "name of the view", but I don't have any specific segue or whatsoever.
This is the code for that specific "button" which I call in the viewDidLoad function:
func setupMiddleButton() {
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
var menuButtonFrame = menuButton.frame
menuButtonFrame.origin.y = self.view.bounds.height - menuButtonFrame.height
menuButtonFrame.origin.x = self.view.bounds.width/2 - menuButtonFrame.size.width/2
menuButton.frame = menuButtonFrame
menuButton.backgroundColor = UIColor.white
menuButton.layer.cornerRadius = menuButtonFrame.height/2
menuButton.setImage(UIImage(named: "klein_fototoestel_2"), for: UIControlState.normal) // 450 x 450px
menuButton.contentMode = .scaleAspectFit
menuButton.addTarget(self, action: #selector(menuButtonAction), for: UIControlEvents.touchUpInside)
self.view.addSubview(menuButton)
self.view.layoutIfNeeded()
}
func menuButtonAction(sender: UIButton) {
self.selectedIndex = 2
}
I tried to perform the behaviour I want by delegating the tab bar controller with the following code but this function is never called when the central button is selected (though the correct view shows up..!):
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print("the selected index is : \(tabBar.items?.index(of: item))")
}
What I really want to know is what is the correct way to implement that behaviour I want. Remembering that all views have a navigationController before. I read a lot of people suggesting using UserDefaults to store the index of the previous controller but to be honest I really don't think that's appropriate.
Any help is appreciated.
Thanks in advance.
I think you were on the right track - just need to get the correct connections.
In this diagram (it's kinda big - easier to read if you open it in a new tab), you see a "standard" UITabBar structure. The key is putting a default "do-nothing" view controller as the 3rd tab, and then adding a "special" view controller which will be loaded via code:
Then, your "action" function will look something like this:
func menuButtonAction(sender: UIButton) {
// Don't navigate to the tab index
//self.selectedIndex = 2
// instead, load and present the view you really want to see
if let vc = storyboard?.instantiateViewController(withIdentifier: "SpecialVC") as? SpecialViewController {
vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
self.present(vc, animated: true, completion: nil)
}
}
You can see and download a working example here: https://github.com/DonMag/SWTabsWithSpecialTab
I am working on a small project with a few separate view controllers on my storyboard, and have have created a button the shows a UITableViewController, but I needed a way for the user to get back to the home page. I have created a button on top of the MainTableVC, and when I run the app, it shows the button. What I need is for the button to simply show my main view controller which is called just view controller. I am still learning so every step forward is a leap for me. Here is the code of the viewDidLoad, where I created the button.
let button1 = UIButton(frame: CGRect(origin: CGPoint(x: self.view.frame.width / 2 - 25, y: self.view.frame.height - 70), size: CGSize(width: 50, height: 50)))
button1.backgroundColor = UIColor.blue
self.navigationController?.view.addSubview(button1)
I also do have a UITableViewController listed in the class. Thank you everyone for your help, I appreciate it. So to summarize, I need to connect the button1 I created to the viewcontroller, (because you can not just put a button on top of a tableview and then just control click to the other view and set "show". That actually makes it easier to say, I need to code the aspect of simply cntrl dragging from one button to a view and setting "show". Thanks so much everyone.
As much i understood.. you can manually create a button in your MainViewController using and add Target To it
let button1 = UIButton(frame: CGRect(origin: CGPoint(x: self.view.frame.width / 2 - 25, y: self.view.frame.height - 70), size: CGSize(width: 50, height: 50)))
button1.backgroundColor = UIColor.blue
button1.addTarget(self, action: #selector(MainViewController.actionOpenTableView(_:)), forControlEvents: .TouchUpInside)
self.navigationController?.view.addSubview(button1)
Also create function actionOpenTableView in Your class capturing the
Target of button 1 where you can push/present TableViewController(:here MyTableViewController) using segue or programmically.
func actionOpenTableView(btn:UIButton){
//if using segue of motherboard
// self.performSegueWithIdentifier("MoveToTableView", sender: self)
//if using programmically
let tableVC = self.storyboard?.instantiateViewControllerWithIdentifier("MyTableVC")as! MyTableViewController
self.navigationController?.pushViewController(tableVC, animated: true)
}
if using pprogrammically make sure you provide StoryboardID to your TableviewController in Storyboard.
once you get on your TableViewController you can either use default back button.. or create custom method as follow for getting back to your MainViewController from MyTableViewController
#IBAction func mBackActionBtn(sender: AnyObject) {
self.navigationController?.popViewControllerAnimated(true)
}
Firstly, you shouldn't add a button directly to your navigation controller. If you want to add a custom button, instead use the following:
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Title", style: .plain, target: self, action: #selector(navButtonPressed))
You can then implement the method for the action:
func navButtonPressed() {
// if pushed onto nav vc:
// _ = self.navigationController?.popViewController(animated: true)
// if presented modally (as suggested in your comment:
self.dismiss(animated: true, completion: nil)
}
I want to make an app in which my navigation bar appears on all pages. When I click on any row of side menu(done through SWRevealViewController), I want the page that opens to have a navigation bar on top. In the image below, I want the same navigation bar as the HomeViewController on the page that has "Menu" label. How can I do this? Please help. I am new to iOS. I am doing this in Xcode 8 and Swift 3.
EDIT : I want something like this: I have placed the side menu button on the reveal view controller. I can see it on the front view controller at runtime but how to connect the target and action of revealviewcontroller then, so that the side menu opens? If this is done then my problem of navigation controller on "Menu" label page will be solved automatically
Suppose outlet of menu is btn_Menu. In controller's view did load I set bar button's action and target programmatically.
btn_Menu.target = self.revealViewController()
btn_Menu.action = #selector(SWRevealViewController.revealToggle(_:))
Have a look at this image structure that you need. Sorry not very clear but perhaps solve your issue:
You need to add all the starting points of your ViewControllers in a NavigationController of their own so in this case you need to embed the ViewController which has the menu label in a NavigationController and make the side menu segue to the NavigationController not the ViewController
hope my answer helps you
1) create a new ViewController Class called 'BaseViewController'
2) in the BaseViewController viewDidLoad add the following code and change the images names and targets also add the left button for the menu
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: "imagename"), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn1.addTarget(self, action: #selector(Class.Methodname), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
let btn2 = UIButton(type: .custom)
btn2.setImage(UIImage(named: "imagename"), for: .normal)
btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn2.addTarget(self, action: #selector(Class.MethodName), for: .touchUpInside)
let item2 = UIBarButtonItem(customView: btn2)
self.navigationItem.setRightBarButtonItems([item1,item2], animated: true)
3) make the viewControllers which you will show from the side menu like the one with menu label inherits from BaseViewController and in it's viewDidLoad make it call super.viewDidLoad()
4) embed the viewControllers which you will show from the side menu in a navigationController
Using Container View may help.
Replace the UIView in the middle (Content) with a Container View and that container can be a UINavigationController. And to avoid having 2 NavigationBars you can hide the NavigationBar of the ContainerView.
The blue highlighted view is the ContainerView inside the Controller that is implementing SideMenu
You also need to add Navigation Controller for sabe bar Controller
Follow the steps :
Select side bar viewcontroller > go to Editior menu > Embed in > Click Navigation Controller