UIButton selector not called inside Navigation bar - ios

I'm trying to add a UIButton to the center of my navigation bar.
My navigation controller is initialised with a tab bar controller.
Then I create a UIButton with a custom image.
My problem is that the selector is never called, even if I can see that the button is really pressed, as the image animation (when pushing the button) is played.
Here is my code:
let navigationController = UINavigationController(rootViewController: tabBarController)
let image = UIImage(named: "logo")
let but = UIButton(type: .Custom)
navigationController.navigationBar.addSubview(but)
but .setImage(image, forState: .Normal)
but.frame=CGRectMake((self.view.frame.size.width-image!.size.width)/2.0, (navigationController.navigationBar.frame.size.height-image!.size.height)/2.0, image!.size.width, image!.size.height)
but.addTarget(self, action: #selector(self.initTabView), forControlEvents: .AllEvents)
but.addTarget(self, action: #selector(self.initTabView), forControlEvents: .TouchDown)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController = navigationController
Any hint will be appreciated.

// try like this
// Classname is , in which class initTabView method exist you need to give that class name
but.addTarget(self, action: #selector(Classname.initTabView), forControlEvents: .TouchUpInside)

Look at forControlEvents:
let but = UIButton(type: .Custom)
but.frame = CGRectMake(0, 0, 100, 40)
but.backgroundColor = UIColor.redColor()
but.setTitle("Button", forState: UIControlState.Normal)
but.addTarget(self, action: #selector(MyTabBarController.initTabView), forControlEvents: UIControlEvents.TouchUpInside)
self.navigationItem.titleView = but
To prevent multiple touch on your button:
// default is false
but.exclusiveTouch = true

Related

Dismiss Keyboard from Another View Controller

I'm using SJSegmentedViewController to make my view controller segmented.
I have one view controller named as PlaceReviewsVC where I have added textView for review. For post this review I'm adding Post bar button instance of UIBarButtonItem at navigationItem.rightBarButtonItem in my placeDetailSegmentController which are instance of SJSegmentedViewController.
Now issue is when I click on post button, I'm not able to dismiss keyboard.
I have tried following code to add post button in segmented view controller.
let headerVC = PlaceImagesVC.viewController()
let reviewVC = PlaceReviewsVC.viewController()
reviewVC.delegate = self
reviewVC.title = "Reviews"
let placeDetailSegmentController = SJSegmentedViewController()
placeDetailSegmentController.delegate = self
placeDetailSegmentController.title = "Pedal Studio"
placeDetailSegmentController.headerViewController = headerVC
placeDetailSegmentController.segmentControllers = [reviewVC]
placeDetailSegmentController.headerViewHeight = 280
placeDetailSegmentController.selectedSegmentViewHeight = 2.0
placeDetailSegmentController.selectedSegmentViewColor = .white
let button = UIButton(type: .custom)
button.setImage(#imageLiteral(resourceName: "icon_back").withRenderingMode(.alwaysTemplate), for: .normal)
button.tintColor = .white
button.addTarget(self, action:#selector(backButtonTapped), for:.touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
button.contentMode = .scaleAspectFit
button.imageEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
let leftButton = UIBarButtonItem(customView: button)
placeDetailSegmentController.navigationItem.leftBarButtonItem = leftButton
let btnPost = UIButton(type: .custom)
btnPost.setTitle("POST", for: .normal)
btnPost.addTarget(self, action:#selector(btnPostTapped), for:.touchUpInside)
btnPost.titleLabel?.setFont(Typography.getFont(.PoppinsMedium, size: 12.0), .white)
btnPost.setTitleColor(.menuColor, for: .normal)
btnPost.setTitleColor(.darkGray, for: .highlighted)
btnPost.contentMode = .scaleAspectFit
let rightButton = UIBarButtonItem(customView: btnPost)
placeDetailSegmentController.navigationItem.rightBarButtonItem = rightButton
self.navigationController?.pushViewController(placeDetailSegmentController, animated: true)
where inside btnPostTapped method I have wrote following code to dismiss keyboard. But didn't work.
#objc func btnPostTapped() {
self.view.endEditing(true)
}
How can I dismiss keyboard from one view controller to another?
You should change your code to dismiss keyboard as follows:
#objc func btnPostTapped() {
AppDelegate.shared.window?.endEditing(true)
}
Our app's base is window, So when you perform any event on window it will affect on whole app. I hope this will fix your issue.
Hide keyboard from anywhere
UIApplication.shared.sendAction(#selector(UIApplication.resignFirstResponder), to: nil, from: nil, for: nil)
or
Get the required viewcontroller instance from navigation hierarchy and resign keyboard as:
requiredViewController.textField.resignFirstResponder()
or
requiredViewController.view.endEditing(true)

Custom button in navigation bar - added and gets tapped but not visible

I try to add custom back button in navigation controller. I create button like this
func setupBackButton() {
let backButton = UIButton.init(type: .custom)
backButton.addTarget(self, action: #selector(backButtonHandler(_:)), for: .touchUpInside)
backButton.setTitleColor(UIColor.white, for: .normal)
backButton.setTitle("<", for: .normal)
backButton.tintColor = UIColor.white
let barBackButton = UIBarButtonItem(customView: backButton)
self.navigationItem.leftBarButtonItem = barBackButton
}
The problem is that button is being added (I can tap it and action on button is being executed) but i can't see button in controller - it is invisible.
Controller's color is blue.
you missed the frame of your button
backButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
dont forget to add the action handler
func backButtonHandler(_ sender : UIButton) {
}
try this :
func setupBackButton(){
let backBtn : UIBarButtonItem = UIBarButtonItem(title: "<", style: UIBarButtonItemStyle.plain, target: self, action:#selector(backToPreviousVC))
self.navigationItem.leftBarButtonItem = backBtn
backBtn.tintColor = UIColor.white
}
func backToPreviousVC() {
self.navigationController?.popViewController(animated: true)
}
call setupBackButton() in viewDidLoad

Setting target/action on UIButton programmatically?

In my app I have a flow which goes like: The user press a button which changes the UIBarButtonItems and when the user clicks on one of them, its changes to something else. However I get the following exception when click on one of them.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[App.MapViewController revealLeftView]: unrecognized selector sent to instance 0x7fbc90c404c0'
First the buttons added in the storyboard gets their action set like this:
menuButton.action = #selector(PBRevealViewController.revealLeftView)
toolboxMenuButton.action = #selector(PBRevealViewController.revealRightView)
When the user clicks on a button elsewhere on the screen, I change the UIBarButtons like this:
let leftButton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
leftButton.setImage(UIImage(named: "close"), for: UIControlState.normal)
//add function for button
leftButton.addTarget(self, action: #selector(MapViewController.cancelAddFields), for: UIControlEvents.touchUpInside)
//set frame
leftButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
let leftBarButton = UIBarButtonItem(customView: leftButton)
let rightButton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
rightButton.setImage(UIImage(named: "add"), for: UIControlState.normal)
//add function for button
rightButton.addTarget(self, action: #selector(MapViewController.confirmCreateFields(sender:)), for: UIControlEvents.touchUpInside)
//set frame
rightButton.frame = CGRect(x: 0, y: 0, width: 24, height: 20)
let rightBarButton = UIBarButtonItem(customView: rightButton)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = rightBarButton
self.navigationItem.leftBarButtonItem = leftBarButton
This works as it should, and when the user clicks the close-button, I change the UIBarButtonItems like this:
let leftButton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
leftButton.setImage(UIImage(named: "MenuIcon_1"), for: UIControlState.normal)
//add function for button
//leftButton.addTarget(self, action: #selector(MapViewController.cancelAddFields), for: UIControlEvents.touchUpInside)
//set frame
leftButton.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
let rightButton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
rightButton.setImage(UIImage(named: "ToolsIcon_1"), for: UIControlState.normal)
//add function for button
//rightButton.addTarget(self, action: #selector(MapViewController.cancelAddFields), for: UIControlEvents.touchUpInside)
//set frame
rightButton.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
leftButton.addTarget(self, action: #selector(PBRevealViewController.revealLeftView), for: UIControlEvents.touchUpInside)
rightButton.addTarget(self, action: #selector(PBRevealViewController.revealRightView), for: UIControlEvents.touchUpInside)
let leftBarButton = UIBarButtonItem(customView: leftButton)
let rightBarButton = UIBarButtonItem(customView: rightButton)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = rightBarButton
self.navigationItem.leftBarButtonItem = leftBarButton
It shows all up good, but when I click on one of them it throws the exception mentioned above. What am I doing wrong? I've tried the .action on the UIBarButtonItem itself, doesn't seem to work either.
It seems that in:
leftButton.addTarget(self, action: #selector(PBRevealViewController.revealLeftView), for: UIControlEvents.touchUpInside)
self (the target) is not actually an instance of PBRevealViewController but a MapViewController. That means that you are telling the button to call method revealLeftView on a MapViewController.
Make sure you are using the correct target.

Why isn't my UIButton in a UIBarButtonItem not showing in the Nav Bar?

I have a UINavigationController which changes the UIBarButtonItem in the top right corner, depending on the state of the app.
When view did load I initialize the buttons I need
var editBarButton: UIBarButtonItem!
var logoutBarButton: UIBarButtonItem!
var showRepositoryBarButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
editButton = UIButton()
editButton.setImage(UIImage(named: "icon pencil"), forState: .Normal)
editButton.frame = CGRectMake(0, 0, 30, 30)
editButton.addTarget(self, action: #selector(UserProfileNavigatorController.onEditClick), forControlEvents: .TouchUpInside)
editBarButton = UIBarButtonItem(customView: editButton)
let logoutButton = UIButton()
logoutButton.setImage(UIImage(named: "icon logout"), forState: .Normal)
logoutButton.frame = CGRectMake(0, 0, 30, 30)
logoutButton.addTarget(self, action: #selector(UserProfileNavigatorController.onLogoutClick), forControlEvents: .TouchUpInside)
logoutBarButton = UIBarButtonItem(customView: logoutButton)
let showRepositoryButton = UIButton()
logoutButton.setImage(UIImage(named: "icon logout"), forState: .Normal)
logoutButton.frame = CGRectMake(0, 0, 30, 30)
logoutButton.addTarget(self, action: #selector(UserProfileNavigatorController.onShowRepositoryOnWebClick), forControlEvents: .TouchUpInside)
showRepositoryBarButton = UIBarButtonItem(customView: showRepositoryButton)
presenter.viewDidLoad()
}
And depending on the situation, I change the buttons displayed in this way
func showUserProfile() {
navigationItem.setRightBarButtonItems([editBarButton, logoutBarButton], animated: false)
Router.showUserProfileInNavigatorController(self)
}
func showRepository(repository: Repository) {
navigationItem.setRightBarButtonItems([showRepositoryBarButton], animated: false)
Router.showRepository(self, repository: repository)
}
Even though this code is actually executed, nothing appears in the top right corner.
The problem was that that code was running in the UINavigationController. Instead, it's the UIViewController who must show the buttons in the UINavigationController.
So just moving the code inside the UIViewController is working.
Note that there are multiple problems with your code. First, note that while UIButton() will return a non-optional, UIImage may return an optional. So you really have no idea now whether you actually have typed the names of your images correctly. I created a simple project using your code above, with no images in it, and duplicated that if the images are nil, that nothing shows.
Then adding images, I only got two images showing. Looking closely at your code, the 3rd image re-defines loginButton but does not set any properties on showRepositoryButton.
Several suggestions:
us "do { ... }" to create a sub context to avoid unintended variable re-use
if using a UIButton, use the designated initializer (UIButton(type:...)
better still, use a UIBarButtonItem(image: ...)
pay really close attention to optionals, and let forced unwrapping crash at the appropriate time (or use an assert, guard, or precondition)
Without drastically modifying your code, here is what works fine for me:
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Howdie!"
do {
let button = UIButton()
let image = UIImage(named: "02-redo")!
button.setImage(image, forState: .Normal)
button.frame = CGRectMake(0, 0, 30, 30)
button.addTarget(self, action: #selector(onEditClick), forControlEvents: .TouchUpInside)
editBarButton = UIBarButtonItem(customView: button)
}
do {
let button = UIButton()
let image = UIImage(named: "03-loopback")!
button.setImage(image, forState: .Normal)
button.frame = CGRectMake(0, 0, 30, 30)
button.addTarget(self, action: #selector(onLogoutClick), forControlEvents: .TouchUpInside)
logoutBarButton = UIBarButtonItem(customView: button)
}
do {
let button = UIButton()
let image = UIImage(named: "04-squiggle")!
button.setImage(image, forState: .Normal)
button.frame = CGRectMake(0, 0, 30, 30)
button.addTarget(self, action: #selector(onShowRepositoryOnWebClick), forControlEvents: .TouchUpInside)
showRepositoryBarButton = UIBarButtonItem(customView: button)
}
navigationItem.setRightBarButtonItems([editBarButton, logoutBarButton, showRepositoryBarButton], animated: false)
}

How to create a custom UIButton with same Buttonsystemitem click effect

I'm creating a custom button item for my navigation bar, and I want it to have the same effect as the button system item ( Slow fade out )
Here is my code :
var button_user : UIImage = UIImage(named:"user.png")!
let button: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as! UIButton
button.setImage(UIImage(named: "user.png"), forState: UIControlState.Normal)
button.setImage(UIImage(named: "user_clicked.png"), forState: UIControlState.Highlighted)
button.addTarget(self, action: nil, forControlEvents: UIControlEvents.TouchUpInside)
button.frame = CGRectMake(0, 0, 28, 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton
You should change UIButtonType.Custom to UIButtonType.System for that:
let button = UIButton(type: UIButtonType.System)
button.setImage(UIImage(named: "user.png"), forState: UIControlState.Normal)
button.setImage(UIImage(named: "user_clicked.png"), forState: UIControlState.Highlighted)
button.addTarget(self, action: nil, forControlEvents: UIControlEvents.TouchUpInside)
button.frame = CGRectMake(0, 0, 28, 30)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton
Edit
Updated for Swift 2.0
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
func buttonClicked(sender:UIButton)
{
dispatch_async(dispatch_get_main_queue(), {
if isHighLighted == false{
sender.highlighted = true;
isHighLighted = true
}else{
sender.highlighted = false;
isHighLighted = false
}
});
}
OR
button.setShowsTouchWhenHighlighted(true)
Edit: You should use UIBarButtonItem instead of UIButton in the navigation bar. That will do.
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "backbutton"), style: UIBarButtonItemStyle.Plain, target: self, action: "buttonClicked:")
And also add the method
func buttonClicked(sender: AnyObject){
//Enter your code here
}
add more "images" for the UIControlState accordingly

Resources