I am starting an app programmaticaly with no storyboards. When I try to make my UITabBarController the root view controller it looks like The background color should be red and the tab item should be a house. What could be the problem?
SceneDelegate code:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = TabBarController()
window?.makeKeyAndVisible()
}
HomeViewController code:
import UIKit
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
// Do any additional setup after loading the view.
}
}
TabBarController code:
import UIKit
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setupTab()
}
func setupTab(){
let homeVC = HomeViewController()
homeVC.tabBarItem = UITabBarItem(title: "Home", image: UIImage(named: "House"), tag: 0)
let homeNC = UINavigationController(rootViewController: homeVC)
tabBarController?.viewControllers = [homeNC]
}
}
The work for setting up the tab view controller needs to be done while you are setting up the scene in the SceneDelegate. The HomeViewContoller's viewDidLoad was never being called.
var homeNavigationController : UINavigationController!
var secondHomeNavigationController : UINavigationController!
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
let tabBarController = TabBarController()
homeNavigationController = UINavigationController.init(rootViewController: HomeViewController())
secondHomeNavigationController = UINavigationController.init(rootViewController: HomeViewController())
tabBarController.viewControllers = [homeNavigationController, secondHomeNavigationController]
// let item1 = UITabBarItem(title: "Home", image: UIImage(named: "House"), tag: 0)
let item1 = UITabBarItem(tabBarSystemItem: .featured, tag: 0)
let item2 = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 1)
homeNavigationController.tabBarItem = item1
secondHomeNavigationController.tabBarItem = item2
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
}
class TabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setupTab()
}
func setupTab(){
}
}
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
// Do any additional setup after loading the view.
}
}
Related
I am trying to add ImageView to NavigationBar. I did all setups in SceneDelegate to setup a rootviewcontroller and seems like it works, but when I try to add Title or Image it does no show it.
SceneDelegate :
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: scene)
window?.rootViewController = UINavigationController(rootViewController: MainTabController())
window?.makeKeyAndVisible()
}
NavigationBar
NavigationController:
class FeedController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
setupNavController()
}
func configureUI() {
view.backgroundColor = .white
let imageView = UIImageView(image: UIImage(named: "twitter_logo_blue"))
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
#objc func addTapped() {
//
}
func setupNavController() {
if #available(iOS 15.0, *) {
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.configureWithDefaultBackground()
UINavigationBar.appearance().standardAppearance = navigationBarAppearance
UINavigationBar.appearance().compactAppearance = navigationBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
}
}
}
Do not embed UITabBarController in UINavigationController. Rather embed each UIViewController into UINavigationController before adding them to UITabBarController. Here is an example.
Modify the scene(_:willConnectTo:options) method like below.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = MainTabViewController()
self.window = window
window.makeKeyAndVisible()
}
Here is the MainTabBarController class.
class MainTabViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let mainVC = UINavigationController(rootViewController: ViewController())
mainVC.tabBarItem = UITabBarItem(title: "Tab 1", image: UIImage(systemName: "circle"), selectedImage: UIImage(systemName: "circle.fill"))
let secondVC = UINavigationController(rootViewController: SecondViewController())
secondVC.tabBarItem = UITabBarItem(title: "Tab 2", image: UIImage(systemName: "square"), selectedImage: UIImage(systemName: "square.fill"))
viewControllers = [mainVC, secondVC]
}
}
Now modify titleView of navigationItem in UIViewController.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
setupNavController()
}
func configureUI() {
view.backgroundColor = .white
let imageView = UIImageView(image: UIImage(systemName: "sun.max.circle.fill"))
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
func setupNavController() {
if #available(iOS 15.0, *) {
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.configureWithDefaultBackground()
UINavigationBar.appearance().standardAppearance = navigationBarAppearance
UINavigationBar.appearance().compactAppearance = navigationBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
}
}
}
I'm not using storyboard. I'm embedding my MainViewController into a navigation controller.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let mainVC = MainViewController(nibName: nil, bundle: nil)
let navigationController = UINavigationController(rootViewController: mainVC)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
But it's only showing black screen instead of my mainVC.
You should use window like this
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
This below code finally works for me.
In SceneDelegate,
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let rootViewController = MainViewController()
let navController: UINavigationController = UINavigationController(rootViewController: rootViewController)
self.window?.rootViewController = navController
self.window?.makeKeyAndVisible()
}
In MainViewController, this code is taken from #Kudos from comment.
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 15, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
self.navigationController?.navigationBar.isTranslucent = true // pass "true" for fixing iOS 15.0 black bg issue
self.navigationController?.navigationBar.tintColor = UIColor.white // We need to set tintcolor for iOS 15.0
appearance.shadowColor = .clear //removing navigationbar 1 px bottom border.
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
}
I get an nearly black screen when I try to load this view. But if I add view.backgroundColor = .red it shows the color red correctly. Just the settings I did in Storyboard wont get shown.
Here is the code I used:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
guard let windowScene = scene as? UIWindowScene else { return }
window = UIWindow(windowScene: windowScene)
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
window?.rootViewController = mainStoryboard.instantiateViewController(withIdentifier: "ResultsViewController") as! ResultsViewController
window?.makeKeyAndVisible()
}
import UIKit
class ResultsViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
}
}
You seem to have created the ResultsViewController in the storyboard. You'll have to load it from the storyboard to set it as rootViewController.
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
window?.rootViewController = mainStoryboard.instantiateViewController(withIdentifier: "ResultsViewController") as! ResultsViewController
Note: Don't forget to set the identifier for ResultsViewController as "ResultsViewController" in the storyboard.
I try to set a View as first view and get a black background. But it should be red.
This is my SceneDelegate:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = MainNavigationController()
}
This is my MainNavigationController
import UIKit
class MainNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
}
You just need the window to be declared with windowScene initializer instead of the frame initializer.
guard let windowScene = scene as? UIWindowScene else { return }
window = UIWindow(windowScene: windowScene)
Note: Also, make sure storyboard is disabled if you're loading rootViewController programmatically.
You need to add makeKeyAndVisible() after setting root Also assign window scene to window ...
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: UIScreen.main.bounds)
window?.windowScene = windowScene
window?.rootViewController = MainNavigationController()
window?.makeKeyAndVisible()
}
I am trying to get a pod to work.
It is from here:
https://github.com/Ahmadalsofi/SOTabBar
I get no errors until runtime, where I get a long list of what seems like a thread loop of sorts.
Images:
1.Tread Stack
2.Line where error happens
3.Error Message
Where I can trace the error to:
My scene delegate entry to application: (I am not using storyboards)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = MainTabBarVC()
window?.makeKeyAndVisible()
}
}
My MainTabBarVC:
import UIKit
import SOTabBar
class MainTabBarVC: SOTabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let firstVC = SearchVC(nibName: "Main", bundle: nil)
let secondVC = TestVC(nibName: "Main", bundle: nil)
firstVC.tabBarItem = UITabBarItem(title: "Home", image: UIImage(systemName: "mappin.and.ellipse"), selectedImage: UIImage(systemName: "star"))
secondVC.tabBarItem = UITabBarItem(title: "Chat", image: UIImage(named: "secondImage"), selectedImage: UIImage(systemName: "mappin.and.ellipse"))
viewControllers = [firstVC, secondVC]
}
override func loadView() {
super.loadView()
SOTabBarSetting.tabBarHeight = 60.0
SOTabBarSetting.tabBarTintColor = UIColor.red
SOTabBarSetting.tabBarBackground = UIColor.purple
SOTabBarSetting.tabBarCircleSize = CGSize(width: 50.0, height: 50.0)
SOTabBarSetting.tabBarSizeImage = CGFloat(20)
SOTabBarSetting.tabBarSizeSelectedImage = CGFloat(40)
SOTabBarSetting.tabBarAnimationDurationTime = 2
}
}
extension MainTabBarVC: SOTabBarControllerDelegate {
func tabBarController(_ tabBarController: SOTabBarController, didSelect viewController: UIViewController) {
print("Hello")
}
}
My SearchVC and TestVC are just simple VCs with a different background color like:
import UIKit
class SearchVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemRed
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
}
The view controllers themselves are fine, the issue seems to be the pod. I tried looking at their github source but I don't know what could be causing it. So the issue is either the pod or my implementation of it.