Can't click custom added UIBarButtonItem - ios

I've got this transparent Navigation bar, and I can add a custom icon (code below). However it does not seem to respond to clicks, anyone have any idea why this could be caused?
I'm adding this inside a UIViewController which is inside a UINavigationController.
var button: UIButton = UIButton()
button.setImage(UIImage(named: "customBack"), forState: .Normal)
button.frame = CGRectMake(0, 0, 40, 40)
button.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
button.targetForAction("doAction:", withSender: button)
button.backgroundColor = UIColor.brownColor()
var leftItem:UIBarButtonItem = UIBarButtonItem()
leftItem.customView = button
self.navigationItem.leftBarButtonItem = leftItem
self.navigationItem.leftBarButtonItem!.action = "doAction:"
self.navigationController!.navigationItem.leftBarButtonItem = leftItem
I know I shouldn't be adding back items myself but in this exact case it is needed. The icon is added on the fly not before loading the view or w/e.

To try it...
var ysBackButton:UIButton = UIButton(frame:CGRectMake(0, 0, kNavBtnSize, kNavBtnSize))
ysBackButton.setImage(UIImage(named: kBack), forState: UIControlState.Normal)
ysBackButton.addTarget(self, action: Selector("backButtonAction"), forControlEvents:UIControlEvents.TouchUpInside)
var leftBarButton:UIBarButtonItem = UIBarButtonItem(customView: ysBackButton)
self.navigationItem.leftBarButtonItem = leftBarButton

Always just after posting I find out:
I was using
button.targetForAction("doAction:", withSender: button)
Whilst I should be doing:
button.addTarget(self, action: "doAction:", forControlEvents: .TouchUpInside)

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)

Making the nav bar title a button (Swift)

I'm trying to make the title of the nav bar its own button. Users in my app can have multiple profiles, and the nav bar title displays the username of their currently selected profile. Pressing this button should bring up a list of available profiles to choose from (handleShowProfiles). For some reason, the title displays but does not function as a button, it's just static text and touching it does nothing.
let changeProfileContainer : UIView = {
let container = UIView()
container.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
let button = UIButton(type: .custom)
button.setTitle("#username ▼", for: .normal)
button.setTitleColor(.black, for: .normal)
button.frame = container.frame
button.addTarget(self, action: #selector(handleShowProfiles), for: .touchUpInside)
container.addSubview(button)
return container
}()
func configureNavBar() {
self.navigationController?.navigationBar.tintColor = .black
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "send"), style: .plain, target: self, action: #selector(handleSubmitPost))
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "drafts"), style: .plain, target: self, action: #selector(handleDrafts))
self.navigationItem.titleView = changeProfileContainer
}
Any ideas why the button part won't function? In Apple's documentation, it says you have to put the button inside a view, make the button type custom, and change the button's frame from it's default (0, 0, 0, 0). I'm pretty sure this is where I'm messing up but I dunno.
Linked to self invocations in computed property -- See the last portion of Ahmad F's answer
Don't know why, but selectors in computed properties don't seem to work.
I tried adding the container view without computing it and clicking on the button works.
func configureNavBar() {
self.navigationController?.navigationBar.tintColor = .black
let container = UIView()
container.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
let button = UIButton(type: .custom)
button.setTitle("#username ▼", for: .normal)
button.setTitleColor(.black, for: .normal)
button.frame = container.frame
button.addTarget(self, action: #selector(pressTitle), for: .touchUpInside)
container.addSubview(button)
navigationItem.titleView = container
}

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)
}

Add a badge to UIButtonitem with MIBadgeButton-Swift

I'm trying to add a badge to my UIBarButtonItem and for that I have found a this github :
MIBadgeButton-Swift
but I don't know how to use it.
This is my code which makes my custom UIBarButtonItem:
let shopingCartBTN = UIButton(type: UIButtonType.Custom)
shopingCartBTN.setImage(UIImage(named: "shopingCarBarIcon"), forState: UIControlState.Normal)
shopingCartBTN.imageView?.image = UIImage(named: "shopingCarBarIcon")
shopingCartBTN.frame = CGRectMake(0, 0, 60, 30)//Just increase the width of button
shopingCartBTN.setTitle("5", forState: .Normal)
shopingCartBTN.addTarget(self, action: "", forControlEvents: UIControlEvents.TouchUpInside)
let customBarItem = UIBarButtonItem(customView: shopingCartBTN)
self.navigationItem.leftBarButtonItem = customBarItem;
How could I use the MIBadgeButton-Swift to make a badge for my UIBarButtonItem?
Here is two example with custom view and from storyboard
From storyboard by setting custom class :
CODE
#IBOutlet var btnRightBadge: MIBadgeButton!
override func viewDidLoad() {
super.viewDidLoad()
//Custom
let badgeButton : MIBadgeButton = MIBadgeButton(frame: CGRectMake(0, 0, 40, 40))
badgeButton.setTitle("T1", forState: UIControlState.Normal)
badgeButton.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
badgeButton.badgeString = "1";
let barButton : UIBarButtonItem = UIBarButtonItem(customView: badgeButton)
self.navigationItem.leftBarButtonItem = barButton
//From Storyboard
btnRightBadge.badgeString = "5"
}
OUTPUT
You can also use ENMBadgedBarButtonItem-Swift
Try this once.
//Property
var cartBarbuttonItem:MIBadgeButton?
self.cartBarbuttonItem = MIBadgeButton(frame: CGRectMake(40, 5, 40, 44))
self.cartBarbuttonItem?.initWithFrame(frame: CGRectMake(40, 5, 40, 44), withBadgeString: "0", withBadgeInsets: UIEdgeInsetsMake(15, 2, 0, 15))
self.cartBarbuttonItem?.setImage(UIImage(named: "test"), forState: .Normal)
self.cartBarbuttonItem?.setImage(UIImage(named: "test"), forState: .Selected)
self.cartBarbuttonItem?.addTarget(self, action: Selector("loadCart"), forControlEvents: UIControlEvents.TouchUpInside)
self.navigationItem.setLeftBarButtonItem = self.cartBarbuttonItem

Programmatically Setting UINavigation Bar Button

How can I set the UINavigation Bar Button to a particular image programmatically using Swift??
let rightButton: UIButton = UIButton.buttonWithType(UIButtonType.Custom)
rightButton.frame = CGRectMake(0, 0, 40, 40) ;
rightButton.setImage(UIImage(named:"ImageName.png"), forState: UIControlState.Normal)
rightButton.addTarget(self, action: "rightNavButtonClick:", forControlEvents: UIControlEvents.TouchUpInside)
var rightBarButtonItem: UIBarButtonItem = UIBarButtonItem(customView: rightButton)
self.navigationItem.setLeftBarButtonItem(rightBarButtonItem, animated: false);
Try this this should work!!

Resources