i am not using storyboard for this application so here's my SceneDelegate willConnectTo function
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let windowScene = UIWindowScene(session: session, connectionOptions: connectionOptions)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.backgroundColor = .white
let rootViewController = PersonsViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
navigationController.navigationBar.tintColor = .black
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
self.window?.windowScene = windowScene
}
and here is the UITextView configuration function
private func configureTextView() {
textView = UITextView(frame: CGRect(x: 75, y: 120, width: view.frame.width, height: 120))
textView.font = UIFont.systemFont(ofSize: 16)
textView.textColor = .black
textView.backgroundColor = .blue
textView.delegate = self
textView.becomeFirstResponder()
textView.isUserInteractionEnabled = true
textView.keyboardType = .default
view.addSubview(textView)
}
and this is what gets printed in the console
Could not find keyboard scene delegate for interaction view <_UITextLayoutCanvasView: 0x105904be0; frame = (0 0; 375 120); userInteractionEnabled = NO; layer = <CALayer: 0x282ed8ee0>>.
2022-02-07 08:33:15.481898+0200 Project[40078:7478637] [Assert] Could not find window to attach loupe view.
I made sure that the delegate methods get called
The following code works:
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 = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: scene)
self.window?.backgroundColor = .white
let rootViewController = ViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
navigationController.navigationBar.tintColor = .black
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}
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 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.
}
}
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 need to change the initial view controller based on whether voiceover is on or not. I have tried multiple ways but I always get the same error: "Value of type 'AppDelegate' has no member 'window'"
This is what I have in my didFinishLaunchingWithOptions.
print("voiceover: \(voiceOver)") // prints if voice over is on
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "voiceoverViewController")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
Value of type 'AppDelegate' has no member 'window'
You have to declare a window property manually:
var window: UIWindow?
UIApplicationDelegate is just a protocol, it doesn't declare any properties for you.
You don't have to declare window variable manually
It is available in SceneDelegate file in your project
It will have pre defined method :
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions)
Example
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let initialViewController =
storyboard.instantiateViewController(withIdentifier: "voiceoverViewController")
self.window!.rootViewController = initialViewController
self.window!.makeKeyAndVisible()
}
}