I'm diving into UIKit and feel some misunderstanding after using SwiftUI. By following course from Paul Hudson there is some challenges in the end of the project. One of this it's try showing the player’s score in the navigation bar. I try to solve this case but closest solution that I found from Apple's documentation it's:
let scoreButton = UIBarButtonItem(title: NSLocalizedString("Score: \(score)", comment: ""),
style: .done,
target: self,
action: nil)
navigationItem.rightBarButtonItem = scoreButton
But I think adding Button instead of simple Text is unnecessary, I don't need button behavior. Trying to add UITextView() to NavigationBar from storyboard did't work out...
Question: how to add text(better programmatically) to Navigation Bar? something like .toolbarItem with ToolbarItemPlacement: .navigationBarTrailing in SwiftUI. Is it possible or it's a UIKit restriction using only rightBarButtonItem?
You can use titleView property to show a text in the NavigationBar
override func viewDidLoad() {
super.viewDidLoad()
let view = UIView()
view.addSubview(titleLabel)
view.addSubview(scoreLabel)
navigationItem.titleView = view
}
I found solution how to add text to NavBar and yes it's restriction of UIKit thats you have to use UIBarButtonItem
let scoreView = UILabel()
scoreView.text = "Score: \(score)"
let scoreButton = UIBarButtonItem(customView: scoreView)
navigationItem.rightBarButtonItem = scoreButton
Related
I'm trying to follow along with a video course to implement photo gallery with Unsplash.
First I implemented UIViewController with searchbar and navigation bar in it
PhotoCollectionViewController: UIViewController
and manually adding searchbar and navigation bar
//MARK: - Nav bar inelkaar steken hier
private func setupNavigationBar(){
let titleLabel = UILabel()
titleLabel.text = "Photos"
titleLabel.font = UIFont.systemFont(ofSize: 15)
titleLabel.textColor = .black
navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView: titleLabel)
navigationItem.rightBarButtonItems = [addBarButtonItem, actionBarButtonItem]
}
and the same for searchbar
so I got the result as this:
after this the PhotoCollectionViewController: UIViewController inheritance seemed be wrong what I did, and I need to change it to UICollectionViewController
I make then another controller inherited from UICollectionViewController with the same logic PhotoCollectionViewController: UICollectionViewController
It compiles without any issues, but I don't see navigation an search bar anymore
How can I fix this?
May be your collectionView is hiding search bar and navigation bar. check collectionView constraints. (specially top anchor)
// PS: I could comment, but I don't have 50 reputation.
maybe you can try this:
Check the top constraint first of your collectionView. And maybe you can add this code to you viewDidLoad() :
self.navigationController?.setNavigationBarHidden(true, animated: false)
if you use ScollView at fullscreen (SuperView), you can use this :
scrollView.contentInsetAdjustmentBehavior = .never
for searchBar IBOutlet you can add this :
searchBar.becomeFirstResponder()
I have a project with a UITabBarController and a couple of views. Sort of like this:
In this project, the tab bar controller is called by tapping the Tab button on the UIViewController. I would like to get rid of the back button with "Title", and replace it with an "X" icon. When tapped, the "X" icon would dismiss the UITabBarController and return to the caller. I do this all of the time on UINavigationController using a UINavigationItem, but that does not appear to work in this situation. I drag the UINavigationItem to the view and it allows it, but it does not show up on the view and any UIBarButtonItem that I drag and drop on it do not appear.
Is there a way to actually do this? I'd even be ok with leaving the existing back button as it is and just getting rid of "Title"
I figured it out right after posting the question. Just a bit more research is all it took.
To fix this, add the following to the UITabBarController code.
override func viewDidLoad() {
super.viewDidLoad()
let buttonImage = UIImage(named: "back")
let leftButton = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(dismissTabBar))
leftButton.tintColor = UIColor.black
self.navigationItem.leftBarButtonItem = leftButton
}
#IBAction func dismissTabBar() {
self.navigationController?.popToRootViewController(animated: true)
}
This gives me a black back button with my image. When I tap it, it brings me back to the calling 'UIViewController.
I'm not sure why this piece of code which is supposed to embed two bar button items in a navigation controller's toolbar won't work. The toolbar itself is visible when I run my code, but not the bar button items. What am I doing wrong here? Thanks for attention.
class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
//Tool bar appearance
toolbar.barTintColor = UIColor.blackColor()
//Show tool bar by default
self.navigationController?.toolbarHidden = false
//Icons all located in images.xcassets
let homeImage = UIImage(named: "home")
let gameImage = UIImage(named: "logo")
var toolBarItems = [UIBarButtonItem]()
let homeButton = UIBarButtonItem(image: homeImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(NavigationController.toHome))
homeButton.title = "Home"
let gameButton = UIBarButtonItem(image: gameImage, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(NavigationController.toGame))
homeButton.title = "Game"
//Place the bar items in toolBarItems array
toolBarItems.append(homeButton)
toolBarItems.append(gameButton)
//self.toolbar.items = toolBarItems
self.toolbar.setItems(toolBarItems, animated: true)
}//End viewDidLoad
func toHome() {
let homeVC = HomeViewController(nibName: "HomeViewController", bundle: nil)
self.pushViewController(homeVC, animated: true)
}
func toGame() {
let gameVC = GameViewController(nibName: "GameViewController", bundle: nil)
self.pushViewController(gameVC, animated: true)
}
}
Did you create a second .swift file for your dependent controller? You should move this code to the dependant controller file
self.navigationController?.toolbarHidden = false
let button1 = UIBarButtonItem(title: "home", style: .Plain, target: self, action: #selector(SecondViewController.home))
let myToolBar = [button1]
self.setToolbarItems(myToolBar, animated: true)
I am not sure but I think your buttons has size 0. So maybe you should add some constraints or view frame size. You can try debugging using the view hierarchy debugger.
Maybe you just have to replace this self.navigationController?.toolbarHidden = false
With this toolbarHidden = false
I'm confused by your code. Is the class you show us, the one Navigation Controller where all other ViewController depend on or is it itself one dependent ViewController that in this case appears to be a Navigation Controller? Or is it a Navigation Controller by mistake? (not very likely)
Why I ask? At one time you're referring to the parent navigation controller with self.navigationController?.toolbarHidden = false which is not this navigation controller itself. Then in the rest of the code, you refer to this controller itself.
Hope this leads to the right thinking.
How do you create UIBarButtonItem as a plus symbol? I tried giving it the title "+", but I would like it to look more like the plus symbol you would normally create if you used storyboard. Which doesn't have a background or an underline.
It's one of the provided bar button system items.
let addBarButton = UIBarButtonItem(barButtonSystemItem: .add, target: YOUR_TARGET, action: YOUR_SELECTOR)
I think this is what you are looking for:
Swift 4.2 Example
Here is how you do it:
let addBarButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addUser))
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = addBarButton
}
#objc private func addUser() {
// Some code, e.g.
let storyboard = UIStoryboard(name: "CreateNewUser", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "createUser") as! CreateUserVC
self.navigationController?.pushViewController(vc, animated: true)
}
IMPORTANT NOTE: There is a little problem though which many users have pointed out and took me many hours to figure out as well (for iOS 11, 12) that you must put the self.navigationItem.rightBarButtonItem = addBarButton inside the viewDidLoad function otherwise the button's selector won't work. This has something to do, as per other users on StackOverflow, with tap gestures. In my code, one of my view controllers have two buttons assigned outside of viewDidLoad function but there is also use a function to hide the keyboard, which probably causes the buttons to work fine. However, in view controllers of two other projects where I don't show or hide keyboard, the #selector for programatically set navigation bar buttons don't work unless they are defined within viewDidLoad function as in the example above. I hope this tip will save you tons of time in case you face this problem.
Swift 3.0
let addBarButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(ViewController.openSearch))
I create NavTitleView.xib(added in this xib 2 label "TITLE" and "SUBTITLE") and also create for this xib swift file.
Then i want use this xib as navigationItem.titleView
in viewWillAppear i write this code
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
let titleView = NSBundle.mainBundle().loadNibNamed("NavTitleView", owner: self, options: nil)[0] as! NavTitleView
titleView.TitleLabel.text = "My beautiful title"
titleView.SubtitleLabel.text = "My beautiful subtitle"
self.navigationItem.titleView = titleView
}
All works great! But when my view appear - this NavTitleView make jump from left side to center! I don't understand why? How to fix it?
if you have rightBarButtonItem set up, try calling self.navigationItem.rightBarButtonItem = UIBarButton again inside viewWillAppear