I don't use custom navbar with AKSideMenu in swift - ios

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
}

Related

TableView is not updating properly after logout and log in

I have a ProfileView controller where I display the email of the user that is logged in. When I sign out and sign in again the email is updated but the tableview is not updated when new info. Even if it is done the reloading is just appending duplicating rows to the view. Below is my code. Can someone check what I may be doing wrong
import UIKit
import FirebaseAuth
import SDWebImage
import FirebaseDatabase
final class ProfileViewController: UIViewController {
#IBOutlet var tableView: UITableView!
var data = [ProfileViewModel]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let email = Auth.auth().currentUser?.email! else {
return
}
tableView.register(ProfileTableViewCell.self,
forCellReuseIdentifier: ProfileTableViewCell.identifier)
data.append(ProfileViewModel(viewModelType: .info,
title: "Email: \(email ?? "No Email")",
handler: nil))
tableView.register(UITableViewCell.self,
forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
tableView.tableHeaderView = createTableHeader()
}
func createTableHeader() -> UIView? {
guard let email = UserDefaults.standard.value(forKey: "email") as? String else {
return nil
}
let safeEmail = DatabaseManager.safeEmail(emailAddress: email)
let filename = safeEmail + "_profile_picture.png"
let path = "images/"+filename
let headerView = UIView(frame: CGRect(x: 0,
y: 0,
width: self.view.width,
height: 300))
headerView.backgroundColor = .link
let imageView = UIImageView(frame: CGRect(x: (headerView.width-150) / 2,
y: 75,
width: 150,
height: 150))
imageView.contentMode = .scaleAspectFill
imageView.backgroundColor = .white
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 3
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = imageView.width/2
headerView.addSubview(imageView)
StorageManager.shared.downloadURL(for: path, completion: { result in
switch result {
case .success(let url):
imageView.sd_setImage(with: url, completed: nil)
case .failure(let error):
print("Failed to get download url: \(error)")
}
})
return headerView
}
}
extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let viewModel = data[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: ProfileTableViewCell.identifier,
for: indexPath) as! ProfileTableViewCell
cell.setUp(with: viewModel)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
data[indexPath.row].handler?()
}
}
class ProfileTableViewCell: UITableViewCell {
static let identifier = "ProfileTableViewCell"
public func setUp(with viewModel: ProfileViewModel) {
self.textLabel?.text = viewModel.title
switch viewModel.viewModelType {
case .info:
textLabel?.textAlignment = .center
selectionStyle = .none
}
}
}
I think you need to empty data array before appending new object into that array.
just write
data.removeAll() before
data.append(ProfileViewModel(viewModelType: .info, title: "Email: \(email ?? "No Email")", handler: nil)).
I think this will resolve your issue.

UISearchController cancel button dismisses UITabBarController when tapped multiple times in a row

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

iOS - stack fullscreen viewController when presenting another viewController

I have a UITabBarViewController with two tabs. I want to present a viewController fullscreen in one of the tabs. I have used the following code to do so.
let navCtrl = UINavigationController(rootViewController: eventViewController)
navCtrl.modalPresentationStyle = .fullScreen
self.navigationController?.present(navCtrl, animated: true)
It works. And EventViewController is fullscreen. However, when presenting another viewController in EventViewController, EventViewController is still fullscreen. But I want it to shrink in size and stack-up as it normally do( as in the image). In order to do so, I have changed modalPresentationStyle to overCurrentContext.
let navCtrl = UINavigationController(rootViewController: eventViewController)
navCtrl.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(navCtrl, animated: true)
It does so, but it causes another problem: If I change tabs and dismiss EventViewController, the presenting viewController is black as described in this question (none of the answers was helpful).
Basically I want the EventController to be fullscreen but shrink in size when presenting another controller in it. How to do so?
Update
A simple project with the same issue.
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let ctrl = TabZeroViewController()
ctrl.tabBarItem.image = UIImage(named: "archived-task")
ctrl.tabBarItem.title = "One"
let test = TabOneViewController()
test.tabBarItem.image = UIImage(named: "Test")
test.tabBarItem.title = "Test"
let tabBarList = [ctrl, test ]
self.viewControllers = tabBarList.map {
let nav = UINavigationController(rootViewController: $0)
nav.interactivePopGestureRecognizer?.isEnabled = true
return nav
}
}
}
class TabZeroViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.view.backgroundColor = .white
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let ctrl = ModalTableViewController()
let nav = UINavigationController(rootViewController: ctrl)
nav.modalPresentationStyle = .fullScreen
self.navigationController?.present(nav, animated: true)
}
}
class ModalTableViewController: UITableViewController {
override func viewDidLoad() {
self.view.backgroundColor = .red
let button = UIButton()
button.setTitle("Cancel", for: .normal)
button.addTarget(self, action: #selector(dismissModal), for: .allEvents)
let item = UIBarButtonItem()
item.customView = button
self.navigationItem.leftBarButtonItem = item
self.tableView.dataSource = self
self.tableView.delegate = self
}
#objc func dismissModal() {
self.dismiss(animated: true, completion: nil)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Event"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let ctrl = EventViewController()
let nav = UINavigationController(rootViewController: ctrl)
nav.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(nav, animated: true)
}
}
class TabOneViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
class EventViewController: UITableViewController {
override func viewDidLoad() {
self.view.backgroundColor = .red
let button = UIButton()
button.setTitle("Cancel", for: .normal)
button.addTarget(self, action: #selector(dismissModal), for: .allEvents)
let item = UIBarButtonItem()
item.customView = button
self.navigationItem.leftBarButtonItem = item
self.tableView.dataSource = self
self.tableView.delegate = self
}
#objc func dismissModal() {
self.dismiss(animated: true, completion: nil)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Event"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let ctrl = EventViewController()
let nav = UINavigationController(rootViewController: ctrl)
self.navigationController?.present(nav, animated: true)
}
}
Add this code in willConnectTo of SceneDelegate.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = TabBarController()
self.window = window
window.makeKeyAndVisible()
}
While you are on first tab, select a table cell to open the ModalTableViewController. And then change tabs and dismiss ModalTableViewController.
As for example project - presenting view over full screen hides TabBar. But I changed code a bit to propose working solution. Probably you would want to change it a bit, but I hope this will push you in good direction :)
It was actually needed to dismiss ModalTableViewController to avoid black screen.
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let ctrl = TabZeroViewController()
ctrl.tabBarItem.image = UIImage(named: "archived-task")
ctrl.tabBarItem.title = "One"
let test = TabOneViewController()
test.tabBarItem.image = UIImage(named: "Test")
test.tabBarItem.title = "Test"
let tabBarList = [ctrl, test ]
let viewControllers: [UIViewController] = tabBarList.map {
let nav = UINavigationController(rootViewController: $0)
nav.interactivePopGestureRecognizer?.isEnabled = true
nav.tabBarItem = $0.tabBarItem
return nav
}
self.setViewControllers(viewControllers, animated: false)
}
override var selectedViewController: UIViewController? {
get {return super.selectedViewController}
set {
if super.selectedViewController?.presentedViewController != nil {
super.selectedViewController?.dismiss(animated: false, completion: nil)
}
super.selectedViewController = newValue
}
}
}
class TabZeroViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.view.backgroundColor = .white
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let ctrl = ModalTableViewController()
let nav = UINavigationController(rootViewController: ctrl)
nav.modalPresentationStyle = .currentContext
self.present(nav, animated: true)
}
}
class ModalTableViewController: UITableViewController {
override func viewDidLoad() {
self.view.backgroundColor = .red
let button = UIButton()
button.setTitle("Cancel", for: .normal)
button.addTarget(self, action: #selector(dismissModal), for: .allEvents)
let item = UIBarButtonItem()
item.customView = button
self.navigationItem.leftBarButtonItem = item
self.tableView.dataSource = self
self.tableView.delegate = self
}
#objc func dismissModal() {
self.presentingViewController?.dismiss(animated: false, completion: nil)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Event"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let ctrl = EventViewController()
let nav = UINavigationController(rootViewController: ctrl)
nav.modalPresentationStyle = .fullScreen
self.navigationController?.present(nav, animated: true)
}
}
class TabOneViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
}
}
class EventViewController: UITableViewController {
override func viewDidLoad() {
self.view.backgroundColor = .red
let button = UIButton()
button.setTitle("Cancel", for: .normal)
button.addTarget(self, action: #selector(dismissModal), for: .allEvents)
let item = UIBarButtonItem()
item.customView = button
self.navigationItem.leftBarButtonItem = item
self.tableView.dataSource = self
self.tableView.delegate = self
}
#objc func dismissModal() {
self.dismiss(animated: true, completion: nil)
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Event"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let ctrl = EventViewController()
let nav = UINavigationController(rootViewController: ctrl)
self.navigationController?.present(nav, animated: true)
}
}
Good luck!
Try this code to present screen modally:
func getImageFromView() -> UIImage {
let layer = UIApplication.shared.keyWindow?.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer?.frame.size ?? CGSize.zero, false, scale)
if let context = UIGraphicsGetCurrentContext() {
layer?.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image ?? UIImage()
}
return UIImage()
}
/// This is the method to present screen modally
/// - parameter controller: controller instance on which screen will be presented
func presentScreenModally(controller: UIViewController, animated: Bool) {
let loginController = UIStoryboard.loadLoginViewController()//Get instance of controller form storyboard
loginController.bgTranParentImg = getImageFromView()
let bgImage = getImageFromView()
let presentationStyleViewController = UIStoryboard.loadPresentationStyleController()// This is another controller, which I am pasting below
presentationStyleViewController.bgimage = bgImage
presentationStyleViewController.loginController = loginController
presentationStyleViewController.addChild(loginController)
controller.view.window?.addSubview(presentationStyleViewController.view)
loginController.view.frame = presentationStyleViewController.containerView.bounds
presentationStyleViewController.containerView.addSubview(loginController.view)
let navigationController = UINavigationController(rootViewController: presentationStyleViewController)
navigationController.navigationBar.isHidden = true
navigationController.modalPresentationStyle = .fullScreen
controller.navigationController?.present(navigationController, animated: animated, completion: nil)
}
PresentationStyleViewController class:
class PresentationStyleViewController: UIViewController {
#IBOutlet var containerView: UIView!
#IBOutlet var containeTopConstraint: NSLayoutConstraint!
#IBOutlet var containerBottomConstraint: NSLayoutConstraint!
#IBOutlet var backgroundImage: UIImageView!
var bgimage: UIImage?
let topPadding: CGFloat = 30
var loginController: LoginViewController?
override func viewDidLoad() {
super.viewDidLoad()
self.uiSetup()
}
override func viewDidAppear(_ animated: Bool) {
restorePopup()
}
/// Initial UI setup
func uiSetup() {
containeTopConstraint.constant = self.view.frame.size.height
backgroundImage.image = bgimage
}
#IBAction func panGesture(_ sender: UIPanGestureRecognizer) {
guard let piece = sender.view else {return}
let translation = sender.translation(in: piece.superview)
containeTopConstraint.constant = translation.y >= topPadding ? translation.y : topPadding
if sender.state == .ended || sender.state == .cancelled {
if containeTopConstraint.constant > self.view.frame.size.height/4 && translation.y > 0 {
self.dismissPopup()
} else {
self.restorePopup()
}
}
}
/// Dismisses popup and controller
func dismissPopup() {
containeTopConstraint.constant = self.view.frame.size.height
UIView.animate(withDuration: 0.3,
animations: {
self.view.layoutIfNeeded()
}, completion: { (_) in
self.loginController?.btnClick_cross(UIButton())
self.dismiss(animated: false)
})
}
/// Restores popup at initial position
func restorePopup() {
containeTopConstraint.constant = topPadding
UIView.animate(withDuration: 0.3,
animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
}

Programmatically Creating TableViewControllers inside TabBarController will not render labels

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.

Inserting table view row by pressing the button

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()
}
}

Resources