Swift 4 Change UIBarButtonItem System Icon not working - ios

I have two UIBarButtonItems inside my Navigation Item's Right Bar Button Items. I am looking to changing the second UIBarButtonItem only programmatically.
I have created an outlet for this UIBarButtonItem:
#IBOutlet var downloadButton: UIBarButtonItem!
and then I tried to change it like so:
self.downloadButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(PlayerController.downloadButtonPressed(_:)))
But the UIBarButtonItem does not change over, what am I doing wrong?

But the UIBarButtonItem does not change over
There's no reason why it would. All you're doing is replacing the value of a variable downloadButton with a new bar button item. This has no effect on the bar button item still sitting there in the navigation bar — plus, you have destroyed your reference to that bar button item.
You have to reconfigure your navigationItem. You can also set your downloadButton again if you like, but more likely you'll realize you never needed the downloadButton outlet for anything in the first place.
Here's an example from one of my own apps, where I toggle the right bar button item between being a Play button and being a Pause button:
let whichButton : UIBarButtonItem.SystemItem? = {
switch self.mp.currentPlaybackRate {
case 0..<0.1:
return .play
case 0.1...1.0:
return .pause
default:
return nil
}
}()
if let which = whichButton {
let bb = UIBarButtonItem(barButtonSystemItem: which,
target: self, action: #selector(doPlayPause))
self.navigationItem.rightBarButtonItem = bb
}
Notice the last line: I just reach right in and change the navigationItem. Instantly the navigation bar display changes to match.

Related

How to access a right item button on navigation bar in XCUITest?

I am writing UITest cases for my iOS Swift app. In the app I have created a custom right item button on the navigation bar in this way:
let barButtonItem = UIBarButtonItem(customView: customView)
navigationItem.rightBarButtonItem = barButtonItem
Now I don't know how to access this custom right item button in XCUITest and really need some help. Thanks in advance.
You cannot access a UIBarButtonItem, because it is not a real UIElement (it is not a UIView subclass), but you probably want to access the UIButton inside your right bar button item anyway.
There are several ways how you could access the button, here are two ideas:
1. Query the first button in the navigation bar
let rightNavBarButton = XCUIApplication().navigationBars.children(matching: .button).firstMatch
XCTAssert(rightNavBarButton.exists)
That way you access the first UIButton inside a UINavigationBar.
This only works if there is only one button in your navigation bar. So it will break when you add another button.
2. Use an accessibility identifier
You can define a accessibility identifier for the button inside your right bar button item and use that to access it during the test:
In your app:
let barButtonItem = UIBarButtonItem(customView: customView)
barButtonItem.accessibilityIdentifier = "navbarRightItem"
navigationItem.rightBarButtonItem = barButtonItem
In your test:
let rightNavBarButton = XCUIApplication().navigationBars.buttons["navbarRightItem"]
XCTAssert(rightNavBarButton.exists)
Just make sure you are using accessibilityIdentifier and not accessibilityLabel. Because accessibilityLabel will be read by VoiceOver for handicapped users and should contain useful text.
You have to assign an accessibilityIdentifier to the button
barButtonItem.accessibilityIdentifier = “barButtonItemID”
If didn’t work set IsAccessibilityElement to YES/true

How to change a specific bar button item tint color in iOS 10

I have a TabBarController Connected to > NavigationController > TableViewController and i would like to change the tintColor just of a specific page/barButtonItem (not all tab bar buttons) .As you know Runtime Attribute isn't working anymore in Xcode8.
I have looked across the web and tried different solutions but couldn't make it to work out so please help.
thank you
Here's an example written in Swift 3:
let barButtonItem = UIBarButtonItem(image: UIImage(named: "image_path"), style: UIBarButtonItemStyle.done, target: self, action: #selector(ViewController.didTapBarButtonItem))
barButtonItem.tintColor = YOUR_COLOR_HERE
navigationItem.rightBarButtonItem = barButtonItem
You place this in the viewDidLoad method of your view controller.

Custom back bar item button

Rather than going back 1 view controller, I am attempting to pop back to the first view controller under the navigation controller.
func setupBackBarButtons() {
let myBackButton = UIButton()
myBackButton.addTarget(self, action: #selector(presentListController), forControlEvents: .TouchUpInside)
let myCustomBackButtonItem = UIBarButtonItem(customView: myBackButton)
self.navigationItem.backBarButtonItem = myCustomBackButtonItem // This works
self.navigationItem.leftBarButtonItem = myCustomBackButtonItem // This doesn't.
}
func presentListController() {
navigationController?.popToViewController((self.navigationController?.viewControllers[0])!, animated: true)
}
I'm slightly confused to why I can add the custom button to the leftBarButtonItem but not the backBarButtonItem.
I only want to add a target to pop it back to the first view controller but not change the title (Still keep it as back with the < in the in corner). I would do this with the leftBarButtonItem but I'm not to sure how to keep the < in the title.
Do not change the functionality of the back button. When you try to do that, you just break the back button. You can customize the back button's appearance but you cannot change its action. You must provide a nil action and target so that the back button will still work as a back button.
To customize the back button's behavior, change the behavior of the navigation controller itself. Give the navigation controller a delegate and implement navigationController:didShowViewController:animated:. In your implementation, look to see how we got here. If we got here because we popped to it, pop further (to the root).

Navigation Bar Back Button

I have a navigation bar that i want to use this code to change the text but unfortunately the arrow also disappears. So I added a less than sign and it worked but the size of it does not match. Is there anyway to fix this issue?
Here is my code
let backButton: UIBarButtonItem = UIBarButtonItem(title: " < Timeline", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
navigationController?.navigationBar.topItem?.leftBarButtonItem = backButton
Create a transparent view.
Add an imageview of fixed size for the arrow image or you can use UILabel too as its working in your case.
Add another UILabel adjacent to your < label or imageview. You can use padding to make it look uniform.
Add both label or imageview on your transparent view.
Create UIBarButtonItem of your customView and then add it to your navBar.

Reference the back button on UINavigationBar

I need a reference to the back button in the UINavigationBar or UINavigationItem. The Back button in the image below.
I am not customizing the button, thus
navigationItem.backBarButtonItem
navigationItem.leftBarButtonItem
these both are nil.
Is there any way to get a reference to the button without customizing it?
Reference:
backBarButtonItem
leftBarButtonItem
Update: My comment might help to understand why I don't want to customize the back button. :)
The Documentation says this about the backBarButtonItem:
When this item is the back item of the navigation bar—when it is the
next item below the top item—it may be represented as a back button on
the navigation bar. Use this property to specify the back button. The
default value is a button displaying the navigation item’s title.
So the backBarButtonItem is always nil by default because it belongs to the previous view controller. The only way to get a non-nil reference is by customizing it.
If you just want to change the name, however, that can be done in the previous View Controller.
In reference to my use case - Ayush's comment
Till the time I get a concrete solution, I have created a dummy view below the navigation bar (below the back button) to show the tip from. Here is the code.
let v = UIView(frame: CGRectMake(0, 0, 50, 0))
view.addSubview(v)
let tipText = "Here it the back button"
EasyTipView.showAnimated(true,
forView: v,
withinSuperview: view,
text:tipText,
preferences: nil,
delegate: self)
try out this one
let backItem = UIBarButtonItem(title: "Custom Text HERE", style: .Bordered, target: nil, action: nil)
navigationItem.backBarButtonItem = backItem
Try this it might help you.
UINavigationItem *i = [self.navigationController.navigationBar.items firstObject];
i.title = #"Hai";

Resources