I only want to show the table view only when the search bar is clicked (like instagram). If anyone knows how to do this, any information would be helpful.
Here's the relevant code that I have:
class UserSearchController: UICollectionViewController, UICollectionViewDelegateFlowLayout,UISearchBarDelegate, UISearchDisplayDelegate {
let cellId = "cellId"
let searchBar: UISearchBar = {
let sb = UISearchBar()
sb.placeholder = "Search"
return sb
}()
fileprivate func setupNavBarAndSearchBar() {
let navBar = navigationController?.navigationBar
searchBar.delegate = self
navigationController?.navigationBar.addSubview(searchBar)
//Constraints already figured^^
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {searchBar.setShowsCancelButton(true, animated: true)}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.setShowsCancelButton(true, animated: true)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.setShowsCancelButton(false, animated: true)
searchBar.text = ""
}
override func viewDidLoad() {
super.viewDidLoad()
setupNavBarAndSearchBar()
collectionView?.backgroundColor = .white
collectionView?.register(UserProfileVideoCell.self, forCellWithReuseIdentifier: cellId)
searchBar.addSubview(SearchUsersTv) **Compiles error "expected argument type UIView"**
}
Here's what I have for the file "SearchUsersTv" :
class SearchUsersTv: UIView, UITableViewDelegate, UITableViewDataSource {
let cellId = "cellId"
var tableView = UITableView()
let screenHeight = UIScreen.main.bounds.height
let screenWidth = UIScreen.main.bounds.width
override init(frame: CGRect){
super.init(frame: frame)
setup()
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
func setup() {
self.backgroundColor = UIColor.black
tableView = UITableView(frame: CGRect(x: 0, y: 0, width: screenWidth*0.5, height: screenHeight))
tableView.layer.backgroundColor = UIColor.black.cgColor
self.addSubview(tableView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.backgroundColor = .magenta
return cell
}
Now this file above doesn't run since it's not running (it compiles an
error when I try to add this as a sub view in the first file)
Make Your TableView alpha value to "0" first in your StoryBoard.
simply make it "1.0" in your
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {searchBar.setShowsCancelButton(true, animated: true)}
like this
tableView.alpha = 1.0
Hope this helps.It Solved my problem also.
Related
I am trying to create a custom UISearchBar that is placed as the titleView of a navigationController. Using the following code, the suggestionTableView of suggestions appears perfectly; however, It does not recognize any taps. In fact, it is like the suggestionTableView isn't even there because my taps are being sent to another view under the suggestion suggestionTableView. I was told that I could use hitTest(...) to catch these touches, but I don't know how I would implement this in my SuggestionSearchBar or in my ViewController. How can I send these touches to the suggestionTableView?
SuggestionSearchBar
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
//let del: UISearchBarDelegate!
init(del: UISearchBarDelegate, dropDownPossibilities: [String]) {
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
isUserInteractionEnabled = true
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
addSubview(suggestionTableView)
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: bottomAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
func showSuggestions() {
let sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
#objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text?.uppercased() ?? "")
showSuggestions()
possibilities = allPossibilities.filter {$0.contains(searchBar.text?.uppercased() ?? "")}
print(possibilities.count)
suggestionTableView.reloadData()
if searchBar.text == "" || possibilities.count == 0 {
hideSuggestions()
}
}
#objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
extension SuggestionSearchBar: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibilities.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = suggestionTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.backgroundColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 0.75)
if traitCollection.userInterfaceStyle == .light {
cell.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.75)
}
cell.textLabel?.text = possibilities[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//add method that fills in and searches based on the text in that indexpath.row
print("selected")
}
}
ViewController
import UIKit
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"])
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
extension ViewController: UISearchBarDelegate {
func setUpSearchBar() {
searchBar.searchBarStyle = UISearchBar.Style.prominent
searchBar.placeholder = "Search"
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
navigationItem.titleView = searchBar
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print(searchBar.text!)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
}
}
Reviewing your provided code, I can get the UI to work properly and even get the UITableViewDelegate callbacks inside SuggestionSearchBar.
Here are the changes
Suggestion Search Bar
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
var suggestionTableView = UITableView(frame: .zero)
let allPossibilities: [String]!
var possibilities = [String]()
var fromController: UIViewController?
//let del: UISearchBarDelegate!
init(del: UISearchBarDelegate, dropDownPossibilities: [String], fromController: UIViewController) {
self.fromController = fromController
self.allPossibilities = dropDownPossibilities
super.init(frame: .zero)
isUserInteractionEnabled = true
delegate = del
searchTextField.addTarget(self, action: #selector(searchBar(_:)), for: .editingChanged)
searchTextField.addTarget(self, action: #selector(searchBarCancelButtonClicked(_:)), for: .editingDidEnd)
sizeToFit()
addTableView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addTableView() {
guard let view = fromController?.view else {return}
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
view.addSubview(suggestionTableView)
// addSubview(suggestionTableViewse
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: view.topAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: view.rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: view.leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
func showSuggestions() {
let sv = suggestionTableView.superview
sv?.clipsToBounds = false
suggestionTableView.isHidden = false
}
func hideSuggestions() {
suggestionTableView.isHidden = true
}
#objc func searchBar(_ searchBar: UISearchBar) {
print(searchBar.text?.uppercased() ?? "")
showSuggestions()
possibilities = allPossibilities.filter {$0.contains(searchBar.text?.lowercased() ?? "")}
print(possibilities.count)
suggestionTableView.reloadData()
if searchBar.text == "" || possibilities.count == 0 {
hideSuggestions()
}
}
#objc func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
hideSuggestions()
}
}
ViewController
class ViewController: UIViewController {
lazy var searchBar = SuggestionSearchBar(del: self, dropDownPossibilities: ["red","green","blue","yellow"], fromController: self)
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
func setUpUI() {
setUpSearchBar()
}
}
To summarise the changes, the code above tried to add suggestionTableView
to the SearchBarView which is not possible so I initialized SearchBarView with the reference to the parent ViewController which is stored as
var fromController: UIViewController?
This property is later used in addTableView()
private func addTableView() {
guard let view = fromController?.view else {return}
let cellHeight = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "").frame.height
suggestionTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
suggestionTableView.backgroundColor = UIColor.clear
//suggestionTableView.separatorStyle = .none
suggestionTableView.tableFooterView = UIView()
view.addSubview(suggestionTableView)
// addSubview(suggestionTableViewse
suggestionTableView.delegate = self
suggestionTableView.dataSource = self
suggestionTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
suggestionTableView.topAnchor.constraint(equalTo: view.topAnchor),
suggestionTableView.rightAnchor.constraint(equalTo: view.rightAnchor),
suggestionTableView.leftAnchor.constraint(equalTo: view.leftAnchor),
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
])
hideSuggestions()
}
There is another small change
possibilities = allPossibilities.filter {$0.contains(searchBar.text?.lowercased() ?? "")}
in #objc func searchBar(_ searchBar: UISearchBar) {
Result
As long as you are adding the UITableView as a subview to the SearchBar or UINavigationBar, you will keep finding these touch issues.
A possible way to handle this would be have an empty container UIView instance at the call site (ViewController in your case) and ask SuggestionsSearchBar to add it's tableView inside that container.
SuggestionSearchBar(
del: self,
suggestionsListContainer: <UIStackView_Inside_ViewController>,
dropDownPossibilities: ["red","green","blue","yellow"]
)
SuggestionsSearchBar will still manage everything about the tableView's dataSource, delegate, it's visibility etc. It just needs a view that can hold it's tableView from the call site.
UPDATE
I'm highlighting only the relevant parts that need to change - everything else remains the same.
class SuggestionSearchBar: UISearchBar, UISearchBarDelegate {
init(del: UISearchBarDelegate, suggestionsListContainer: UIStackView, dropDownPossibilities: [String]) {
//// All the current setUp
addTableView(in: suggestionsListContainer)
}
private func addTableView(in container: UIStackView) {
//// All the current setUp
container.addArrangedSubview(suggestionTableView)
NSLayoutConstraint.activate([
suggestionTableView.heightAnchor.constraint(equalToConstant: cellHeight*6),
/// We need to assign only height here
/// top, leading, trailing will be driven by container at call site
])
}
}
class ViewController: UIViewController {
lazy var suggestionsListContainer: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
lazy var searchBar = SuggestionSearchBar(
del: self,
suggestionsListContainer: suggestionsListContainer,
dropDownPossibilities: ["red","green","blue","yellow"]
)
func setUpUI() {
setUpSearchBar()
setUpSuggestionsListContainer()
}
func setUpSuggestionsListContainer() {
self.view.addSubview(suggestionsListContainer)
NSLayoutConstraint.activate([
suggestionsListContainer.topAnchor.constraint(equalTo: self.view.topAnchor),
suggestionsListContainer.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
suggestionsListContainer.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
/// Height is not needed as it will be driven by tableView's height
])
}
}
I tried to place a searchBar into the first row of my TableView Cells, but it only throws an error but I don't understand why, can someone tell me what to do? Thanks in advance!
//Custom Cell
class SearchCell: UITableViewCell, UISearchBarDelegate {
let searchbar = UISearchBar()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addSubview(searchbar)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setConstraints() {
searchbar.placeholder = "Country, City"
searchbar.delegate = self
searchbar.searchBarStyle = .minimal
//Constraints
searchbar.translatesAutoresizingMaskIntoConstraints = false
searchbar.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
searchbar.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10).isActive = true
searchbar.widthAnchor.constraint(equalToConstant: 280).isActive = true
searchbar.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
override func awakeFromNib() {
super.awakeFromNib()
setConstraints()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
And this is the ViewController which contains the TableView:
class SearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
!Line 20! let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell") as! SearchCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
return cell
}
}
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
//
view.backgroundColor = .white
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Search"
//Functions
configureTableView()
}
func configureTableView() {
view.addSubview(tableView)
tableView.rowHeight = 80
//Constraints
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
tableView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
tableView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
tableView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
}
}
I watched some tutorials etc. but they didn't help me, so thank you guys!
You need to register your cell with its reuseIdentifier with your tableview first. I don't see that in the code you posted.
After super.viewDidLoad() add something like
tableView.register(SearchCell.self, forCellReuseIdentifier: "SearchCell")
I use a custom search controller that has a tableView for showing the results,
the problem is when tapping the cancel button multiple times it dismisses the tabBarController.
But if i press it normally it acts as it should be.
class UICustomSearchController: UISearchController {
private var suggestedTableView: UITableView!
weak var suggestionDelegate: SearchSuggestionsDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
suggestedTableView = UITableView(frame: CGRect(x: 0, y: searchBar.frame.maxY,
width: view.frame.width,
height: view.frame.height - 70))
suggestedTableView.backgroundColor = UIColor.clear
suggestedTableView.tableFooterView = UIView()
view.subviews.forEach {
if $0.isKind(of: UITableView.self) {
$0.removeFromSuperview()
}
}
view.addSubview(suggestedTableView)
suggestedTableView.dataSource = self
suggestedTableView.delegate = self
suggestedTableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
let tap = UITapGestureRecognizer(target: self, action: #selector(tableTapped))
suggestedTableView.addGestureRecognizer(tap)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
suggestedTableView.removeFromSuperview()
suggestedTableView = nil
dismiss(animated: false, completion: nil)
}
func reloadSuggestions() {
suggestedTableView.reloadData()
}
private func dismissView() {
searchBar.text = ""
suggestedTableView.removeFromSuperview()
dismiss(animated: false, completion: nil)
suggestionDelegate?.didDismissed()
}
// MARK: - Actions
#objc func tableTapped(tap:UITapGestureRecognizer) {
suggestedTableView.removeGestureRecognizer(tap)
let location = tap.location(in: suggestedTableView)
let path = suggestedTableView.indexPathForRow(at: location)
if let indexPathForRow = path {
tableView(suggestedTableView, didSelectRowAt: indexPathForRow)
} else {
dismissView()
}
}
}
extension UICustomSearchController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return suggestionDelegate?.suggestions().count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let list = suggestionDelegate?.suggestions() ?? []
cell.textLabel?.text = list[indexPath.row]
cell.textLabel?.textColor = UIColor.color(from: .blueTabBar)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let list = suggestionDelegate?.suggestions() ?? []
searchBar.text = list[indexPath.row]
searchBar.becomeFirstResponder()
suggestionDelegate?.didSelect(suggestion: list[indexPath.row])
}
}
And in the viewController that has search:
func initSearchViews() {
// Create the search controller and specify that it should present its results in this same view
searchController = UICustomSearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.barTintColor = UIColor.white
searchController.searchBar.tintColor = UIColor.color(from: .blueTabBar)
searchController.searchBar.setValue(Strings.cancel.localized, forKey:"_cancelButtonText")
searchController.suggestionDelegate = self
if let searchTextField = searchController!.searchBar.value(forKey: "searchField") as? UITextField {
searchTextField.placeholder = Strings.search.localized
}
// Make this class the delegate and present the search
searchController.searchBar.delegate = self
}
I tried putting this line in viewController but nothing happened:
definesPresentationContext = true
I want to programmatically create a tabBarView with two tableViewControllers
In my AppDelegate.swift file I added the following at the top:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let mainVC = MainTabBarController()
window?.rootViewController = mainVC
return true
}
I have my MainTabBarController.swift file with the following:
import Foundation
import UIKit
class MainTabBarController : UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setUpTabBar()
}
func setUpTabBar() {
let firstTableViewController = UINavigationController(rootViewController: FirstTableViewController())
firstTableViewController.tabBarItem.image = UIImage(named: "first")
firstViewController.tabBarItem.selectedImage = UIImage(named: "first-selected")
let secondViewController = UINavigationController(rootViewController: SecondTableViewController())
SecondTableViewController.tabBarItem.image = UIImage(named: "second")
SecondTableViewController.tabBarItem.selectedImage = UIImage(named: "second-selected")
viewControllers = [firstViewController, SecondViewController]
guard let items = tabBar.items else { return }
for item in items {
item.imageInsets = UIEdgeInsets(top: 4, left: 0, bottom: -4, right: 0)
}
}
}
I have my FirstTableViewController.swift with the following:
import Foundation
import UIKit
class FirstTableViewController : UITableViewController {
let reuseIdentifier = "firstId"
override func viewDidLoad() {
setUpNavigationBar()
setUpTableView()
}
private func setUpTableView() {
self.tableView.register(FirstTableViewCell.self, forCellReuseIdentifier: reuseIdentifier)
}
func setUpNavigationBar() {
navigationItem.title = "First"
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20)]
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! FirstTableViewCell
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
Here is FirstTableViewCell.swift:
import Foundation
import UIKit
class FirstTableViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUp()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let cellView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.setCellShadow()
return view
}()
let firstItemLabel: UILabel = {
let label = UILabel()
label.text = "Name"
label.textColor = .black
label.font = UIFont.boldSystemFont(ofSize: 16)
return label
}()
func setUp() {
addSubview(cellView)
cellView.addSubview(firstItemLabel)
}
}
With this current view of FirsTableView, all I see is an empty tableView with no data populated even though I should be seeing "Name" inside every cell: https://imgur.com/a/Ecenn3O.
So I tried something different with SecondTableViewController.swift:
import Foundation
import UIKit
class SecondTableViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
let reUseIdentifier: String = "secondId"
let tableView : UITableView = {
let tb = UITableView()
tb.separatorStyle = .none
tb.allowsSelection = false
return tb
}()
override func viewDidLoad() {
super.viewDidLoad()
setUpNavigationBar()
setUpTableView()
}
func setUpNavigationBar() {
navigationItem.title = "Second"
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20)]
}
func setUpTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.register(SecondTableViewCell.self, forCellReuseIdentifier: reUseIdentifier)
view.addSubview(tableView)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reUseIdentifier, for: indexPath) as! SecondTableViewCell
return cell
}
}
Where SecondTableViewCell.swift is very similar to FirstTableViewCell.swift:
import UIKit
class SecondTableViewCell: UITableViewCell {
let cellView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
return view
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUp()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setUp() {
addSubview(cellView)
cellView.addSubview(secondTableViewCellLabel)
}
let secondTableViewCellLabel: UILabel = {
let label = UILabel()
label.text = "Name"
label.textColor = .darkGray
label.font = UIFont.boldSystemFont(ofSize: 16)
return label
}()
}
This renders nothing but a black screen with the tab name up above: https://imgur.com/veTNln6.
I'm new to creating views programmatically and I have no idea what else needs to be done to have the tabBar display both tableViews as intended.
I followed these two videos as a reference:
UITabBar programmatically
UITableView programmatically
Any help would be greatly appreciated.
I have the error:
Value of type 'UIView' has no member 'tableView'
occur when I attempt to change the background of the tableView in the viewWillAppear method.
I expected the table view would already be initialised from the viewDidLoad method.
Where should I be trying to change the colours for the tableview? Should I also be changing the other background colours in the same place?
class settingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// Table view setup
let tableView = UITableView(frame: view.bounds, style: .Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(settingsCell.self, forCellReuseIdentifier: NSStringFromClass(settingsCell))
view.addSubview(tableView)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if nightMode == true {
view.backgroundColor = UIColor.blackColor()
view.tableView.backgroundColor = UIColor.blackColor() // Error here..
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return settings.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(NSStringFromClass(settingsCell), forIndexPath: indexPath) as! settingsCell
// Fetch setting
let cellSetting = settings[indexPath.row]
// Configure Cell
cell.textLabel?.text = cellSetting.name
return cell
}
}
You can make it an instance variable of UITableView like
class settingsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Table view setup
tableView = UITableView(frame: view.bounds, style: .Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(settingsCell.self, forCellReuseIdentifier: NSStringFromClass(settingsCell))
view.addSubview(tableView)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
if nightMode == true {
view.backgroundColor = UIColor.blackColor()
tableView.backgroundColor = UIColor.blackColor()
}
}
This is not the right way of accessing a subview within a view. You can use viewWithTag: to get the subview by tag:
override func viewDidLoad() {
...
tableView.tag = 100
view.addSubview(tableView)
}
...
override func viewWillAppear(animated: Bool) {
...
if let tableView = view.viewWithTag(100) {
tableView.backgroundColor = UIColor.blackColor()
}
}
Alternatively, you make tableView an instance variable if you need to access it in more than just viewWillAppear:
class SettingsViewController: UIViewController ... {
var tableView: UITableView!
...
override func viewDidLoad() {
...
self.tableView = UITableView(frame: view.bounds, style: .Plain)
...
}
override func viewWillAppear(animated: Bool) {
...
self.tableView.backgroundColor = UIColor.blackColor()
}
}
Declare the tableview in global value, then use the tableview in class, see the below code,
class ViewController: UIViewController {
var tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableview.frame = self.view.bounds
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(settingsCell.self, forCellReuseIdentifier: NSStringFromClass(settingsCell))
self.view.addSubview(tableView)
}
override func viewWillAppear(animated: Bool) {
if nightMode == true {
view.backgroundColor = UIColor.blackColor()
tableView.backgroundColor = UIColor.blackColor()
}
}
hope its helpful