5

I do have a non-Storyboard, 100% coded UIViewController, UICollectionView and UICollectionViewCell - works perfect.

here's the code in question:

SceneDelegate not sure if this is relevant, tho.

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 layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        let myController = MyViewController(collectionViewLayout: layout)
        window?.rootViewController = myController
        window?.makeKeyAndVisible()
    }
.
.

ViewController very simple and straight forward...

class MyViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
    let data = loadOnboardingData()
.
.
override func viewDidLoad() {
        super.viewDidLoad()

        collectionView?.backgroundColor = .white
        collectionView?.register(MyPageCell.self, forCellWithReuseIdentifier: "cellId")
        collectionView?.isPagingEnabled = true
        collectionView.showsHorizontalScrollIndicator = false
        collectionView?.tag = myPageControl.currentPage

        setupMyPageControl()

    }

ViewControllerExtention here's the problem: the pushViewController method just doesn't do anything but the modal present works like a charm and I'm not getting what's wrong and why:

extension MyViewController: MyPageCellDelegate {
.
.
func didTabOnActionButton(title: String) {


        let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        guard let homeViewController = storyboard.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else {
            print("Coun't find controller")
            return
        }
        navigationController?.pushViewController(homeViewController, animated: true) <- NO EFFECT
        //present(homeViewController, animated: true, completion: nil) <- WORKS PERFECT!

    }

MyPageCell I set up the Delegate via protocol and it seems that's fine too

protocol MyPageCellDelegate {
    func didTabOnActionButton(title: String)
}

class MyPageCell: UICollectionViewCell {

    var delegate: MyPageCellDelegate?

let myActionButton: UIButton = {
        let button = UIButton(type: .system)
        return button
    }()

myActionButton.addTarget(self, action: #selector(self.doAction), for: .touchUpInside)
.
.
@objc private func doAction(_ sende: Any) {
        delegate?.didTabEndOnboardingActionButton(title: "end Onboarding")
    }

so, any Idea what's wrong with:

navigationController?.pushViewController(homeViewController, animated: true)

EDIT --------------------------------------------------------------------

As pointed out by @Michcio this here: window?.rootViewController = UINavigationController(rootViewController: myController) works half way and as far as I understand it, I'm embedding myController into an UINavigationController which adds the Navigation Bar to the current and following controllers.

But that's not what I need!

What I need is a clean and simple one for the onboarding i.e. MyViewController and the HomeViewController should be one with a Tab- and Navigation Bar

Basically starting from scratch after onboarding.

I used to solve this in the previous version editing the AppDelegate first Method like this (in this example I used Storyboards):

extension AppDelegate {

    func showOnboarding() {
        if let window = UIApplication.shared.keyWindow, let onboardingViewController = UIStoryboard(name: "Onboarding", bundle: nil).instantiateInitialViewController() as? OnboardingViewController {
            onboardingViewController.delegate = self
            window.rootViewController = onboardingViewController
        }
    }

    func hideOnboarding() {
        if let window = UIApplication.shared.keyWindow, let mainViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() {
            mainViewController.view.frame = window.bounds
            UIView.transition(with: window, duration: 0.5, options: .transitionCrossDissolve, animations: {
                window.rootViewController = mainViewController
            }, completion: nil)
        }
    }
}

and in the Delegate itself like this:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let isFirstRun = true // logic to determine goes here
    if isFirstRun {
        showOnboarding()
    }
    return true
}

but I'm seriously not getting the new SceneDelegate or simply don't understand it

Really would appreciate if someone could past some code here for re-use.

1
  • Hmm, can you provide some sample project with your problem, i.e. on github? It will be easier to understand what's wrong here. Commented Oct 9, 2019 at 9:31

1 Answer 1

3

It didn't work, because you are set MyViewController as window.rootViewController. Just change line in SceneDelegate to:

window?.rootViewController = UINavigationController(rootViewController: myController)

Sign up to request clarification or add additional context in comments.

3 Comments

but when I do this, how can I make sure, that the first ViewController that shows up on App start, is going to be the MyViewController?
You set it as rootViewController :)
please see the EDIT section of my post above .... it's still unclear and I'm terribly sorry for my lack of understanding this new SceneDelegate

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.