Programmatically UISearchBar not showing up - ios

I created a programatically UISearchBar (not UISearchController) and I set it as tableview header. However, it's not showing up. Anyone might know why is that?
Outside of the class:
var searchBar = UISearchBar()
Inside the viewDidLoad method.
searchBar.barTintColor = UIColor(red:0.54, green:0.77, blue:0.80, alpha:1.0)
searchBar.placeholder = "Cauta cheltuieli"
searchBar.backgroundImage = #imageLiteral(resourceName: "searchbarback")
tableView.tableHeaderView = searchBar
tableView.setContentOffset(CGPoint.init(x: 0, y: 44), animated: true)

You forget to give the searchbar any dimension so the size will be zero.
Try setting the dimension by setting the frame or use the constructor with a frame.
let searchbar = UISearchBar(frame: CGRect(x: 0.0, y: 0.0, height: 50.0, width: tableView.frame.width))

Related

Custom View in Navigationbar titleView disappear iOS Swift

I'm having a problem with the titleView in navigation bar in iOS. I've created a custom view for the titleView, but every time I push another controller, the titleView immediately appear and disappear when I go back to the first view controller. Here's my code.
override func viewDidLoad() {
super.viewDidLoad()
let logo = UIImage(named: "img_appbar_logo")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 180, height: 40))
logoContainer.backgroundColor = UIColor.clear
animatedLogo = UIImageView(frame: CGRect(x: 0, y: 0, width: logoContainer.frame.width, height: logoContainer.frame.height))
animatedLogo.contentMode = .scaleAspectFit
animatedLogo.clipsToBounds = true
animatedLogo.image = logo
logoContainer.addSubview(animatedLogo)
navigationItem.titleView = logoContainer
}
I've already fixed the issue related to titleView in Navigation bar. I found out that after I push another controller and pop back, the titleView will be replaced by the view of empty UILabel in the NavigationItem. That's why the titleView appear then disappear.
How I fixed the issue?
I added the custom view directly to the navigation bar. Here's the code
let logo = UIImage(named: "img_appbar_logo")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 180, height: 40))
logoContainer.backgroundColor = UIColor.red
animatedLogo = UIImageView(frame: CGRect(x: 0, y: logoContainer.frame.origin.y, width: logoContainer.frame.width, height: logoContainer.frame.height))
animatedLogo.contentMode = .scaleAspectFit
animatedLogo.clipsToBounds = true
animatedLogo.image = logo
logoContainer.addSubview(animatedLogo)
navigationController?.navigationBar.addSubview(logoContainer) <--- new
//navigationItem.titleView = logoContainer <---- old
Then remove the view on viewWillDisappear
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
logoContainer.removeFromSuperview()
}
Set the titleView in viewWillAppear since the titleView gets replaced by the title in the previous controller

Header of viewcontroller doesn't fit

So the original setup of the app that I inherited has the navigation bar set like so (this is in my AppDelegate):
private func configureNavigationController(_ navigationController: UINavigationController) {
navigationController.navigationBar.isTranslucent = false
self.window?.rootViewController = navigationController
let imageView = UIImageView(image: UIImage(named: "logo-white"))
imageView.contentMode = UIViewContentMode.scaleAspectFit
let center = (navigationController.topViewController?.view.frame.width)! / 2.0 - 44
let titleView = UIView(frame: CGRect(x: center, y: 0, width: 88, height: 44))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
UINavigationBar.appearance().barTintColor = UIColor.navBackground
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().addSubview(titleView)
}
This creates the nav bar across every view controller correctly with the image in the center, however I have some new functionality that needs to be on top of everything, and this logo file - logo-white - is still showing up over top.
That's the real problem I want to solve - so if my attempted solution below is wrong, let me know and tell me the correct way.
Anyway, I tried commenting out the code above in my AppDelegate, and putting it in the specific viewcontrollers that I need it for
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image: UIImage(named: "logo-white"))
imageView.contentMode = UIViewContentMode.scaleAspectFit
let center = (navigationController!.topViewController?.view.frame.width)!// / 2.0 - 44
let titleView = UIView(frame: CGRect(x: center, y: 0, width: 88, height: 44))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
navigationItem.titleView = imageView
However this doesn't work - I can either get the logo to show up on the left side of the screen, or slightly off of center, but never center.
I am guessing that this is because the bar has a back button and a little settings icon as well on either side.
So, how do I do this correctly?
Is there a way to make it so that something can cover the logo? Is the solution to move it into my individual view controllers?
Here's a picture of the overlap here. The logo, "Pinyada" should not be covering this up at all - this is a third party library that should be on top of everything.
You may try this :
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image: UIImage(named: "logo-white"))
imageView.contentMode = .scaleAspectFit
imageView.frame = CGRect(x: 0, y: 0, width: 88, height: 44)
navigationItem.titleView = imageView
}
If you have navigationItem.titleView , another titleview is not necessary.
Sometimes, if you need a much more precise control of the titleView, you can add a customTitleView. Add the following codes in the viewController and you can get what you want.
let imageView = UIImageView(image: UIImage(named: "logo-white"))
private func addTitleView(){
let nbar = (navigationController?.navigationBar)!
let width = nbar.frame.width
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.frame = CGRect.init(x: (width - 88) / 2.0 , y: 0, width: 88, height: 44)
nbar.addSubview(imageView)
}
private func removeTitleView(){
imageView.removeFromSuperview()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addTitleView()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
removeTitleView()
}
BTW, UINavigationBar.appearance().addSubview(titleView)
This method will result in all navigationBar with the same titleView, which is not what you want.
I figured it out.
One of the other modifications to my header was taking up too much space. I made it smaller and the image fits perfectly.
I moved all of the code generating the header out of the AppDelegate and into my navigation protocol, where I then popped it into each and every viewcontroller.

UISearchController expands off screen when tapped

We're having a weird issue with using a UISearchController as an item in a navigation bar. It's set as the left bar button item and when a user taps to start searching, the search bar expands to the right off the side of the screen.
Below is the code for creating the UISearchController:
resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.hidesNavigationBarDuringPresentation = false
controller.searchBar.delegate = self
controller.delegate = self
controller.searchBar.frame = CGRect(x: 0, y: 0, width: 266, height: 44.0)
let searchBarView = UIView(frame: controller.searchBar.frame)
searchBarView.addSubview(controller.searchBar)
controller.searchBar.backgroundImage = UIImage(named: "searchBarBG")
controller.searchBar.barTintColor = .white
controller.searchBar.subviews[0].subviews.flatMap(){ $0 as? UITextField }.first?.tintColor = Constants.Colors.Red
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: searchBarView)
return controller
})()
When the screen first loads, it looks like this.
After tapping on the search bar, it changes to look like this.
I have no idea what's causing this. After lots of searching, I tried changing self.definesPresentationContext = false; and self.extendedLayoutIncludesOpaqueBars = true as well as adjusting similar checkboxes in the storyboard. Any tips?
Edit: This only seems to happen on iOS 11. In 10.3, the search bar actually shrinks a little to accommodate the Cancel button but ultimately takes up the same amount of space.
I ended up fixing this by overriding the didPresentSearchController and didDismissSearchController methods as part of the UISearchControllerDelegate.
extension ContactUsViewController: UISearchControllerDelegate {
func didPresentSearchController(_ searchController: UISearchController)
{
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: 266, height: 44.0)
}
func didDismissSearchController(_ searchController: UISearchController)
{
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: 266, height: 44.0)
}
}
If you don't need the added functionality of UISearchBarController you can directly use UISearchBar, which has a more predictable resizing behavor:
let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: 200, height: 20))
searchBar.delegate = self
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: searchBar)
Note that if you use the built-in cancel button or other similar features you'll have to manually handle them in the delegate methods.

Creating a UIContainerView() programmatically and changing its height

I'm creating a container view programmatically. However, i'm not able to change its height. I'm setting it programmatically but without any effect.
let supportView: UIView = UIView()
let containerView = UIView()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
self.containerView.frame = CGRect(x: self.view.frame.size.width - 100, y: 200, width: 225, height: 70)
print(self.containerView.frame.height)
self.containerView.backgroundColor = UIColor.gray
self.containerView.layer.cornerRadius = 20
self.view.addSubview(self.containerView)
let controller = storyboard!.instantiateViewController(withIdentifier: "Storyboard2")
addChildViewController(controller)
containerView.addSubview(controller.view)
controller.didMove(toParentViewController: self)
}
I created the view controller with identifier "Storyboard2" in the storyboard. And i've set its height to 70 there too. But without any luck.
Any Help? Thanks
You have not set the clipsToBounds on containerView, and the default value of that property is false.
Add this line just under you are setting the containerView's frame:
containerView.clipsToBounds = true
Also, as some reading material, i would like to present to you this discussion about the clipsToBounds property.

How to add a search bar to the navigation bar

I'd love to add a search bar managed by UISearchController to the right side of my navigation bar.
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
searchController.searchBar.placeholder = "Search"
searchController.searchBar.searchBarStyle = .Minimal
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: 200.0, height: 44.0)
searchController.hidesNavigationBarDuringPresentation = false
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: searchController.searchBar)
When I tap on the search bar (so it becomes active) it covers the whole navigation bar (while overlapping everything else) instead of the little part. How can I fix its frame?
Wrapping the search bar in a UIView seems to do the trick.
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: 200.0, height: 44.0)
let barContainer = UIView(frame: searchController.searchBar.frame)
barContainer.backgroundColor = UIColor.clearColor()
barContainer.addSubview(searchController.searchBar)
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: barContainer)

Resources