Is this code correct for enable large titles? - swift

import UIKit
class GoalViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Goal"
view.backgroundColor = .white
}
I have ever made Large Titles on this way yet, but now, the VC is completely white, can someone tell me why?

Have you tried this:
navigationItem.largeTitleDisplayMode = .always
You can also use .never for never showing large title or .automatic for inheriting the mode from the previous navigation item

Related

Remove extra space on top of UISearchController in UINavBar

I added a UISearchController in the navigation bar. But it has this extra top padding which I don't want. I used UIsearchController instead of a UITextField because I need its searchResultsController. Is there a way to remove the extra space, or a way to copy the searchResultsController behavior with UITextField. I created the view programmatically btw.
override func viewDidLoad() {
setupSearchBar()
}
func setupSearchBar(){
let searchController = UISearchController(searchResultsController: ResultController)
searchController.searchResultsUpdater = self
searchController.searchBar.placeholder = "Search"
navigationItem.searchController = searchController
navigationController?.navigationBar.backgroundColor = .yellow
}
Set 'automaticallyAdjustsScrollViewInsets' to false
Setting the automaticallyAdjustsScrollViewInsets value to false

Changing textfield font of UISearchBar also changes it's height

I am changing UISearchBar's UITextField font size:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [.font: UIFont.systemFont(ofSize: 17)]
or
searchBar.searchTextField.font = .systemFont(ofSize: 17)
This is the same font size value as the default. But UISearchBar also changes its height. Looks like it's a little bit bigger than the default height value. How I can fix it?
Default UISearchBar height:
After font size change (pay attention that actual font size is the same as on screenshot above):
UPDATE:
I have a storyboard with UITabBarViewController in it. Then I have two UIViewControllers connected to UITabBarViewController. One of them is empty and another one contains UINavigationController with connected sample VIewController which is UITableViewController. Here is a sample code of test ViewController:
import UIKit
class ViewController: UITableViewController {
private lazy var searchController: UISearchController = {
let searchController = UISearchController(searchResultsController: nil)
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.autocapitalizationType = .none
searchController.searchBar.placeholder = "Search"
searchController.searchBar.barStyle = .black
searchController.searchBar.tintColor = .black
searchController.searchBar.keyboardAppearance = .light
return searchController
}()
override func viewDidLoad() {
super.viewDidLoad()
title = "TEST"
navigationItem.searchController = searchController
navigationItem.searchController?.searchBar.searchTextField.font = .systemFont(ofSize: 17)
definesPresentationContext = true
}
}

Need to show navigation title while using searchBar in navigationBar

I need to show large navigation title while search with searchBar, but when I'm clicking on Searchbar or starting to type my NavigationTitle is replaced with SearchBar. I checked methods for navigationItem and didn't find any suitable.
Does anybody know how can we always show title, even while searching?
Here is my code
class FavouriteVC: UIViewController {
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Favourite"
navigationItem.searchController = searchController
navigationItem.largeTitleDisplayMode = .always
}
}
And here are shots
screen with NavTitle
screen without NavTitle
Seems like UISearchController has a hidesNavigationBarDuringPresentation that prevents the navigation bar from hiding when set to false
Include:
searchController.hidesNavigationBarDuringPresentation = false
in your viewDidLoad and if I've understood your issue right, this should do what you need.

What is the difference if I create a UILabel as part of my LoadView() compared to creating a fileprivate uilabel?

I have always been programmatically building my UI and recently I was starting to learn more about loadView(). I realized that when I used loadView() I would write code this way:
override func loadView() {
super.loadView()
let EarningsView = UIView()
let EarningsLabel = UILabel()
EarningsView.translatesAutoresizingMaskIntoConstraints = false
EarningsLabel.translatesAutoresizingMaskIntoConstraints = false
let earningsText = NSAttributedString(string: "My Earnings", attributes: self.stringAttrib)
EarningsLabel.attributedText = earningsText
EarningsLabel.textColor = .black
EarningsLabel.backgroundColor = .white
EarningsView.addSubview(EarningsLabel)
EarningsView.addViewBorder(borderColor: UIColor.black.cgColor, borderWith: 0.5, borderCornerRadius: 0.0)
EarningsView.backgroundColor = .white
NSLayoutConstraint.activate([
EarningsView.widthAnchor.constraint(equalTo: contentStack.widthAnchor),
EarningsView.topAnchor.constraint(equalTo: contentStack.topAnchor),
EarningsView.centerXAnchor.constraint(equalTo: contentStack.centerXAnchor),
view.addSubview(EarningsView)
}
As Compared to how I have always written it:
fileprivate lazy var earningsView : UIView = {
var view = UIView()
let EarningsLabel = UILabel()
EarningsLabel.translatesAutoresizingMaskIntoConstraints = false
let earningsText = NSAttributedString(string: "My Earnings", attributes: self.stringAttrib)
EarningsLabel.attributedText = earningsText
EarningsLabel.textColor = .black
EarningsLabel.backgroundColor = .white
view.addSubview(EarningsLabel)
view.addViewBorder(borderColor: UIColor.black.cgColor, borderWith: 0.5, borderCornerRadius: 0.0)
view.backgroundColor = .white
view.addSubview(EarningsLabel)
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(earningsView)
NSLayoutConstraint.activate([
earningsView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
earningsView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
earningsView.widthAnchor.constraint(equalTo: self.view.widthAnchor),
earningsView.heightAnchor.constraint(equalTo: self.view.heightAnchor,multiplier: 0.20),
])
Is one way better than the other? Or is this more of a personal preference.
The purpose of the loadView() and viewDidLoad() has to do with lifecycle events. Essentially everything happens in order and certain things have to happen at specific times. For example if you attempt to give parent view controller a class after it's been loaded then you'll run into issues. The fix for that is to use loadView() and add it there. Essentially making your class, function, or whatever happen as a part of loading the view, before it's presented.
Typically people have a better understanding when you consider how the view appears with its associated methods as an example.
viewWillAppear()
It's much easier to set up the view in this method than setting it up after the fact. You really only want to do that with processes that are fast and don't hang up the application.
viewDidAppear()
Attempting to set something on the view here requires that you use the main thread and pass everything else to a background thread.
The same lifecycle concept applies to loading. It's also worth noting that you probably shouldn't be using loadView on any modern applications that are built-in Interface Builder. It's typically more useful to use loadView() when working with manually created views granted it won't make much of a difference, but using viewDidLoad() can present certain challenges at times, although rarely.

How to change Navigation Bar back to translucent after making it transparent

I have a view controller in my navigation stack that needs to have a transparent navigation bar, while still showing the back button.
I'm able to achieve that with one line of code inside viewWillAppear:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
However, when I try to go back to the previous view, I'm setting the background image back to nil or .none but I'm losing the translucent effect that was previously on there when I do that.
I've tried setting all the following options in viewWillDisappear and none seem to bring the translucency back. It just appears white no matter what I do. The shadow on the bottom is also gone too:
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.barStyle = .default
self.navigationController?.navigationBar.backgroundColor = .none
self.navigationController?.navigationBar.setBackgroundImage(.none, for: .default)
Initial Navigation Bar:
Transparent Navigation Bar:
After Transitioning Back:
In viewWillAppear make the navigation bar transparent
override func viewWillAppear(_ animated: Bool) { self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
And backg to translucent in viewWillDisappear
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = false
}
After spending time poking around in the UINavigationBar internals, I did discover a simple method that seems to work, and does not require any configuration of the standard UINavigationBar attributes we've previously fiddled with to achieve transparency. The following is tested working on iOS 12.2.x:
class TallNavigationBar: UINavigationBar {
private lazy var maskingView: UIView = {
let view = UIView(frame: bounds)
view.backgroundColor = .clear
return view
}()
var isTransparent = false {
didSet {
guard isTransparent != oldValue, let bkgView = subviews.first else { return }
bkgView.mask = isTransparent ? maskingView : nil
}
}
}
Obviously, whenever fiddling (even slightly) with undocumented internals: use at your own risk!
This worked for my app which needs to revert to an opaque navigation bar after popping from a transparent navigation bar.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
navigationController?.navigationBar.shadowImage = nil
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.backgroundColor = nil
}