UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Project 7 -- can't get second tab button to appear

Forums > 100 Days of Swift

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        if let tabBarController = window?.rootViewController as? UITabBarController {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "NavController")
            vc.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 1)
            tabBarController.viewControllers?.append(vc)
        }
        return true
    }

window is nil, thus the second tab button does not appear. I copied this code from the finished project in the repo, so where else do I need to look?

How does window get set?

3      

Hi @ha1neux! It also took me some time to figure out, as the course is a "bit" outdated and I would say substantial changes were introduced. You need to add those lines in SceneDelegate file instead.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

  var window: UIWindow?

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    if let tabBarController1 = window?.rootViewController as? UITabBarController {
      let storyboard = UIStoryboard(name: "Main", bundle: nil)
      let vc = storyboard.instantiateViewController(withIdentifier: "NavController")
      vc.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 1)
      tabBarController1.viewControllers?.append(vc)
    }

    // This creates second tab bar item
//    if let tabBarController2 = window?.rootViewController as? UITabBarController {
//      let storyboard = UIStoryboard(name: "Main", bundle: nil)
//      let vc = storyboard.instantiateViewController(withIdentifier: "NavController")
//      vc.tabBarItem = UITabBarItem(tabBarSystemItem: .mostViewed, tag: 2)
//      tabBarController2.viewControllers?.append(vc)
//    }

    guard let _ = (scene as? UIWindowScene) else { return }
  }

  ...
}

4      

that sort of works except clicking the "Top Rated" icon produces two "Most Recent" buttons -- sorry can't figure out how to post pictures.

https://imgur.com/a/z0V2sAE

3      

Did you make any set up in tabview for 2 tabitems in your Stroryboard file by any chance? If you could share your full code (maybe via github) I can have a look what is the issue then, otherwise it is diffucult to say what triggers that...

3      

https://github.com/ha1neux/Project7 should be the git repo if I did it right. It's public (why not).

3      

Ok, the issue as follows:

In your Storyboard file you have indicated Tab Bar Controller screen in Identity Inspector StoryboardID as "NavController". You have to remove it and instead choose Navigation Controller screen and update its StoryboardID as "NavController" and voila!

ADDITION:

To get rid of purple warning is you might have guessed you need to use async downloading so you can replace this piece of code:

 if let url = URL(string: urlString) {
            if let data = try? Data(contentsOf: url) {
                parse(json: data)
            }
        }

with creating something like this

 func downloadData(fromURL: String) {
        guard let url = URL(string: fromURL) else { return }

        Task {
            do {
                let (data, _) = try await URLSession.shared.data(from: url)
                parse(json: data)
            } catch let error {
                print(error)
            }
        }
    }

and then calling that function in viewDidLoad

3      

The window property in AppDelegate is typically set up in the SceneDelegate (or AppDelegate if you're not using the SceneDelegate).

In iOS 13 and later, SceneDelegate became responsible for managing the window. This is because iOS 13 introduced multi-window support for iPad.

Here's how you typically set up the window property:

SceneDelegate (iOS 13 and later or 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(windowScene: windowScene)
    let rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourRootViewController")
    window?.rootViewController = rootViewController
    window?.makeKeyAndVisible()
}

}

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    let rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourRootViewController")
    window?.rootViewController = rootViewController [.](http://gwacalculator.net/)
    http://gwacalculator.net/
    window?.makeKeyAndVisible()
    return true
}

}

Make sure that in your storyboard, you have set the initial view controller properly.

If window is still nil after checking this, ensure that you don't have any conflicts or issues in your storyboard, and that you don't accidentally overwrite it somewhere else in your code. I follow the same process to resolve my website issue:

3      

Hey @twostraws, this project needs revision to work correctly. Not sure where that is on your priority list, but I have been offered positions using UIKit and not SwiftUI yet.

3      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.