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.
Related
I'm trying to pass data from UIView contains UITableView to UIViewController but unfortunately, it doesn't work.
Model:
struct Recipes: Codable {
let recipes: [Recipe]
}
struct Recipe: Codable {
let title: String?
let image: String?
let pricePerServing: Double?
let readyInMinutes, servings: Int?
}
The data should be passed from this view
HomeView:
protocol RecipesDetailsSelectActionDelegate: class {
func recipeDetails(recipeTitle: String)
}
class HomeView: UIView {
var recipes: Recipes?
var recipesDetails = [Recipe]()
let indicator = ActivityIndicator()
weak var homeViewDidSelectActionDelegate: HomeViewDidSelectActionDelegate?
weak var recipeDetailsViewSelectActionDelegate: RecipesDetailsSelectActionDelegate?
override init( frame: CGRect) {
super.init(frame: frame)
layoutUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var foodTableView: UITableView = {
let foodTableView = UITableView()
foodTableView.translatesAutoresizingMaskIntoConstraints = false
foodTableView.backgroundColor = .customVeryLightGray()
foodTableView.delegate = self
foodTableView.dataSource = self
foodTableView.register(HomeTableViewCell.self, forCellReuseIdentifier: "HomeTableViewCell")
foodTableView.rowHeight = UITableView.automaticDimension
foodTableView.estimatedRowHeight = 100
foodTableView.showsVerticalScrollIndicator = false
foodTableView.separatorStyle = .none
return foodTableView
}()
}
extension HomeView: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recipesDetails.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTableViewCell", for: indexPath) as! HomeTableViewCell
let url = URL(string: recipesDetails[indexPath.row].image ?? "Error")
cell.foodImage.kf.setImage(with: url)
cell.foodTitle.text = recipesDetails[indexPath.row].title
if let readyInMin = recipesDetails[indexPath.row].readyInMinutes {
cell.cookingTimeInfoLabel.text = "\(readyInMin) Minutes"
}
if let pricePerServing = recipesDetails[indexPath.row].pricePerServing {
cell.priceInfoLabel.text = String(format: "%.2f", pricePerServing / 100)
}
if let serving = recipesDetails[indexPath.row].servings {
cell.servesInfoLabel.text = "\(serving)"
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
recipeDetailsViewSelectActionDelegate?.recipeDetails(recipeTitle: recipesDetails[indexPath.row].title ?? "Error")
}
}
HomeViewController:
class HomeViewController: UIViewController {
lazy var mainView: HomeView = {
let view = HomeView(frame: self.view.frame)
view.recipeDetailsViewSelectActionDelegate = self
return view
}()
override func loadView() {
super.loadView()
view = mainView
}
}
extension HomeViewController: RecipesDetailsSelectActionDelegate {
func recipeDetails(recipeTitle: String) {
let vc = RecipesDetailsViewController()
vc.mainView.recipeTitle = recipeTitle
self.show(vc, sender: nil)
}
}
The data should be passed to this view
RecipesDetailsView:
class RecipesDetailsView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
layoutUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var recipeTitle: String?
lazy var tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 100
tableView.showsVerticalScrollIndicator = false
tableView.separatorStyle = .none
tableView.backgroundColor = .white
tableView.register(IngredientsTableViewCell.self, forCellReuseIdentifier: "IngredientsTableViewCell")
return tableView
}()
extension RecipesDetailsView: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "IngredientsTableViewCell", for: indexPath) as! IngredientsTableViewCell
cell.recipeTitleLabel.text = recipeTitle
return cell
}
}
RecipesDetailsViewController:
class RecipesDetailsViewController: UIViewController {
lazy var mainView: RecipesDetailsView = {
let view = RecipesDetailsView(frame: self.view.frame)
view.backgroundColor = .white
return view
}()
override func loadView() {
super.loadView()
view = mainView
}
}
I have implemented a custom table view cell which appears but without the separator until you scroll. In the viewDidAppear I have set the separator style, the label border is not overlapping the cell edges. Help
Before Scrolling
After Scrolling
Larger Sim Window
On device testing
The pattern is MVVM with a custom cell.
Model
import Foundation
struct OAuthList {
let providers: [String]
init() {
self.providers = OAuthProviders.providers
}
}
View Model
import Foundation
struct OAuthListViewModel {
var providerList: [String]
init(providers: [String]) {
self.providerList = providers
}
}
LoginViewController
import UIKit
class LoginViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var providerButtons = OAuthListViewModel(providers: OAuthProviders.providers)
override func viewDidLoad() {
super.viewDidLoad()
let attributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17)]
self.navigationController?.navigationBar.titleTextAttributes = attributes
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.barTintColor = #colorLiteral(red: 1, green: 0.738589704, blue: 0.9438112974, alpha: 1)
self.navigationItem.title = "LOGIN / SIGNUP"
self.navigationItem.leftBarButtonItem?.tintColor = .white
self.navigationItem.leftBarButtonItem?.isEnabled = false
self.tableView.separatorColor = .white
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.register(CustomCell.self, forCellReuseIdentifier: TextCellIdentifier.textCellIdentifier)
self.tableView.layoutMargins = UIEdgeInsets.zero
self.tableView.separatorInset = UIEdgeInsets.zero
self.tableView.tableFooterView = UIView()
}
}
extension LoginViewController {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return providerButtons.providerList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TextCellIdentifier.textCellIdentifier, for: indexPath) as! CustomCell
let row = indexPath.row
cell.backgroundColor = #colorLiteral(red: 1, green: 0.738589704, blue: 0.9438112974, alpha: 1)
cell.buttonLabel.text = providerButtons.providerList[row]
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(providerButtons.providerList[indexPath.row])
}
}
Custom Cell
class CustomCell: UITableViewCell {
var labelText: String?
var buttonLabel: UILabel = {
var label = UILabel()
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: TextCellIdentifier.textCellIdentifier)
self.addSubview(buttonLabel)
buttonLabel.translatesAutoresizingMaskIntoConstraints = false
buttonLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
buttonLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
buttonLabel.textColor = UIColor.white
}
override func layoutSubviews() {
if let labelText = labelText {
buttonLabel.text = labelText
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You can hide the separator and simply add UIView to act as a separator inside your custom cells
Enlarge your simulator window or try it on an actual device not sim.
When the sim window is small enough it can have a hard time displaying separators in a tableview since the separators are normally only 0.5pt in height.
A good indicator that the issue I mentioned above is occurring is when you scroll the tableview on the simulator and random separators start to appear while some are hidden. Which is what appears to be happening in your second screenshot.
I want to use my custom navbar, I do all the settings on the board, but when I run my application comes first as I do when I go to different pages, the standard navbar comes in standard settings.
I have already tried add navbar with code
This code block is LeftMenuViewController
import UIKit
public class LeftMenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView?
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override public func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView(frame: CGRect(x: 0, y: (self.view.frame.size.height - 54 * 5) / 2.0, width: self.view.frame.size.width, height: 54 * 5), style: .plain)
tableView.autoresizingMask = [.flexibleTopMargin, .flexibleBottomMargin, .flexibleWidth]
tableView.delegate = self
tableView.dataSource = self
tableView.isOpaque = false
tableView.backgroundColor = .clear
tableView.backgroundView = nil
tableView.separatorStyle = .none
tableView.bounces = false
self.tableView = tableView
self.view.addSubview(self.tableView!)
}
// MARK: - <UITableViewDelegate>
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
switch indexPath.row {
case 0:
self.sideMenuViewController!.setContentViewController(UINavigationController(rootViewController: self.storyboard!.instantiateViewController(withIdentifier: "haberlerVC")), animated: true)
self.sideMenuViewController!.hideMenuViewController()
case 1:
self.sideMenuViewController!.setContentViewController(UINavigationController(rootViewController: self.storyboard!.instantiateViewController(withIdentifier: "duyurularVC")), animated: true)
self.sideMenuViewController!.hideMenuViewController()
case 2:
self.sideMenuViewController!.setContentViewController(UINavigationController(rootViewController: self.storyboard!.instantiateViewController(withIdentifier: "firmalarVC")), animated: true)
self.sideMenuViewController!.hideMenuViewController()
case 3:
self.sideMenuViewController!.setContentViewController(UINavigationController(rootViewController: self.storyboard!.instantiateViewController(withIdentifier: "birimlerVC")), animated: true)
self.sideMenuViewController!.hideMenuViewController()
default:
break
}
}
// MARK: - <UITableViewDataSource>
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 40
}
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection sectionIndex: Int) -> Int {
return 7
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier: String = "Cell"
var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: cellIdentifier)
cell!.backgroundColor = .clear
cell!.textLabel?.font = UIFont(name: "HelveticaNeue", size: 21)
cell!.textLabel?.textColor = .white
cell!.textLabel?.highlightedTextColor = .lightGray
cell!.selectedBackgroundView = UIView()
}
var titles = ["Haberler", "Duyurular", "Firmalar", "Yönetim Kurulu", "Bölge Müdürlüğü", "Hizmet Birimleri", "Öneri Şikayet"]
var images = ["haberler", "duyurular", "firmalar", "yonetim", "bolgemudurlugu", "birimler", "oneri" ]
cell!.textLabel?.text = titles[indexPath.row]
cell!.imageView?.image = UIImage(named: images[indexPath.row])
return cell!
}
}
//This code block is my RootViewController and it's not have any navigation bar on storyboard
import UIKit
import AKSideMenu
public class RootViewController: AKSideMenu, AKSideMenuDelegate {
override public func awakeFromNib() {
super.awakeFromNib()
self.menuPreferredStatusBarStyle = .lightContent
self.contentViewShadowColor = .black
self.contentViewShadowOffset = CGSize(width: 0, height: 0)
self.contentViewShadowOpacity = 0.6
self.contentViewShadowRadius = 12
self.contentViewShadowEnabled = true
self.backgroundImage = UIImage(named: "menubg")
self.delegate = self
if let storyboard = self.storyboard {
self.contentViewController = storyboard.instantiateViewController(withIdentifier: "contentViewController")
self.leftMenuViewController = storyboard.instantiateViewController(withIdentifier: "leftMenuViewController")
}
}
// MARK: - <AKSideMenuDelegate>
public func sideMenu(_ sideMenu: AKSideMenu, willShowMenuViewController menuViewController: UIViewController) {
print("willShowMenuViewController")
}
public func sideMenu(_ sideMenu: AKSideMenu, didShowMenuViewController menuViewController: UIViewController) {
print("didShowMenuViewController")
}
public func sideMenu(_ sideMenu: AKSideMenu, willHideMenuViewController menuViewController: UIViewController) {
print("willHideMenuViewController")
}
public func sideMenu(_ sideMenu: AKSideMenu, didHideMenuViewController menuViewController: UIViewController) {
print("didHideMenuViewController")
}
}
Error is visual,
first run my custom navbar
https://user-images.githubusercontent.com/13061013/59485353-3227bf80-8e7e-11e9-81d7-cec51bc328be.png
tapped diffrent menu page or same page
https://user-images.githubusercontent.com/13061013/59485352-3227bf80-8e7e-11e9-832c-a18211167272.png
If I am not wrong, you want to have your own customized navigation bar in all the UIViewControllers.
open your AppDelegate.swift add below code.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let color : UIColor = UIColor.white
let buttonFont : UIFont = UIFont.systemFont(ofSize: 14.0)
let titleFont : UIFont = UIFont.systemFont(ofSize: 18.0)
let attributes = [
NSAttributedStringKey.foregroundColor : color,
NSAttributedStringKey.font : buttonFont
]
UINavigationBar.appearance().titleTextAttributes = [
NSAttributedStringKey.foregroundColor : color,
NSAttributedStringKey.font : titleFont
]
UINavigationBar.appearance().barTintColor = UIColor.blue
UINavigationBar.appearance().tintColor = UIColor.white
return true
}
I created a UITabBarController with two controllers , as first I have a
ViewController with UIButton on it and the second is UITableViewController, how can I by pressing on btn in ViewController insert new row in tableView?
Should it be done with custom delegation ?
Can someone please show quick example
here is my code
import UIKit
class Home: UIViewController {
var delegate: TableViewDelegate?
lazy var addButton : UIButton = {
let button = UIButton(type: .system)
button.setImage(#imageLiteral(resourceName: "plus_photo"), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(setupRows), for: .touchUpInside)
return button
}()
#objc func setupRows() {
delegate?.insertingRows()
}
override func viewDidLoad() {
super.viewDidLoad()
delegate = self as? TableViewDelegate
setupRows()
navigationItem.title = "Test"
view.backgroundColor = .white
view.addSubview(addButton)
addButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
addButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
addButton.heightAnchor.constraint(equalToConstant: 150).isActive = true
addButton.widthAnchor.constraint(equalToConstant: 150).isActive = true
}
}
import UIKit
protocol TableViewDelegate {
func insertingRows()
}
class TableViewTest: UITableViewController , TableViewDelegate {
var items = ["abc", "abcd", "abcde"]
let cellid = "cellid"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomCell.self, forCellReuseIdentifier: cellid)
insertingRows()
}
func insertingRows() {
let indexPath = IndexPath(row: items.count + 1, section: 0)
tableView.insertRows(at: [indexPath], with: .left)
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as! CustomCell
cell.textLabel?.text = items[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
class CustomCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
}
}
You can use tabBar(_:didSelect:) delegate method in your Home viewController.
Your Home VC :
class Home: UIViewController, UITabBarControllerDelegate {
private var selectedIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if tabBarController.selectedIndex == 1 {
if let secondViewController = viewController as? TableViewTest, let index = selectedIndex {
secondViewController.insertingRows(index: index)
}
}
}
#objc func setupRows() {
selectedIndex = 3
}
}
Your TableViewTest TableViewController :
class TableViewTest: UITableViewController {
func insertingRows(index: Int) {
let indexPath = IndexPath(row: index, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .none)
tableView.endUpdates()
}
}
I can use the segmented control to switch between child table view controllers within a container view, but it doesn't show the cells of the first table view controller when I enter the scene for some reason. I have my segment index defaulted at 0, so it shows the highlight on the first segment, but it does not correspondingly show the cells.
Here is the code for the segmentedControl and container view:
import UIKit
class BarMainViewController: UIViewController {
let barSegmentedControl: UISegmentedControl = {
let barItems = ["Newest", "Rewarding", "Saved"]
let segmentedControl = UISegmentedControl(items: barItems)
segmentedControl.selectedSegmentIndex = 0
segmentedControl.addTarget(self, action: #selector(selectionDidChange(_:)), for: .valueChanged)
return segmentedControl
}()
let containerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(barSegmentedControl)
view.addSubview(containerView)
setDefaultVC()
barSegmentedControl.addUnderlineForSelectedSegment()
containerView.topAnchor.constraint(equalTo: barSegmentedControl.bottomAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -49).isActive = true
containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
containerView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
}
#objc func selectionDidChange(_ sender: UISegmentedControl) {
updateView()
barSegmentedControl.changeUnderlinePosition()
}
private func updateView() {
if barSegmentedControl.selectedSegmentIndex == 0 {
remove(asChildViewController: BarRewardingViewController())
remove(asChildViewController: BarSavedViewController())
add(asChildViewController: BarNewestViewController())
} else if barSegmentedControl.selectedSegmentIndex == 1 {
remove(asChildViewController: BarNewestViewController())
remove(asChildViewController: BarSavedViewController())
add(asChildViewController: BarRewardingViewController())
} else {
remove(asChildViewController: BarNewestViewController())
remove(asChildViewController: BarRewardingViewController())
add(asChildViewController: BarSavedViewController())
}
}
private func add(asChildViewController viewController: UITableViewController) {
// Add Child View Controller
addChildViewController(viewController)
// Add Child View as Subview
containerView.addSubview(viewController.view)
// Configure Child View
viewController.view.translatesAutoresizingMaskIntoConstraints = false
// Notify Child View Controller
viewController.didMove(toParentViewController: self)
}
private func remove(asChildViewController viewController: UITableViewController) {
// Notify Child View Controller
viewController.willMove(toParentViewController: nil)
// Remove Child View From Superview
viewController.view.removeFromSuperview()
// Notify Child View Controller
viewController.removeFromParentViewController()
}
private func setDefaultVC() {
containerView.addSubview(BarNewestViewController().view)
}
}
And here is the code for the table view controller:
import UIKit
class BarNewestViewController: UITableViewController {
override func viewDidLoad() {
tableView.register(serviceCell.self, forCellReuseIdentifier: "service")
super.viewDidLoad()
view.backgroundColor = mainBlue
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableView.dequeueReusableCell(withIdentifier: "service", for: indexPath)
}
}
class serviceCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let nameLabel: UILabel = {
let label = UILabel()
label.text = "NAME"
label.font = UIFont(name: "Avnier-Heavy", size: 20)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupViews() {
addSubview(nameLabel)
backgroundColor = lightBlue
nameLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
nameLabel.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
}
}
Because BarNewestViewController subclasses UITableViewController it automatically follows the UITableViewDataSource and UITableViewDelegate protocols e.g. tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int. It does NOT however tell the property tableView that comes with UITableViewController that it's delegate and dataSource is BarNewestViewController.
tableView.dataSource = self
tableView.delegate = self