Mocha
Mocha

Reputation: 2253

Framework ViewController View Not showing

I am trying to create a framework (Login VC) which contains a view controller. I have successfully imported the framework and presented the VC, but the view is not showing. I have a print function in the imported viewDidLoad and it is printing. What am I missing?

Framework VC:

public class LoginVC: UIViewController {

    @IBOutlet weak var button: UIButton! {
        didSet {
            button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
        }
    }

    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override public func viewDidLoad() {
        super.viewDidLoad()
        print("View Loaded") // Firing
    }

    @objc func buttonPressed() {
        print("hello")
    }

}

Framework VC Xib:

Framework VC Xib:

This is view debugger when I present the framework VC

enter image description here

-- Update: This is how I am showing the VC ---

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    let homeViewController = LoginVC()
    homeViewController.view.backgroundColor = UIColor.white
    window!.rootViewController = homeViewController
    window!.makeKeyAndVisible()
    return true
}

-- Update --

Since many comments relate to the app delegate, I first present a general ViewController which then will present my login framework VC.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    let homeViewController = ViewController()
    homeViewController.view.backgroundColor = UIColor.white
    window!.rootViewController = homeViewController
    window!.makeKeyAndVisible()
    return true
}


class ViewController: UIViewController {

   @IBOutlet weak var button: UIButton! {
       didSet {
           button.addTarget(self, action: #selector(presentNext), for: .touchUpInside)
       }
   }

    @objc func presentNext() {
        let loginVC = LoginVC()
        present(loginVC, animated: true, completion: nil)
    }

}

Now, when I present the login framework, all I get is a black screen.

-- Update --

I can change the background color of the view in viewdidLoad, but the xib views are not shown. Why is this?..

Upvotes: 1

Views: 769

Answers (2)

Mocha
Mocha

Reputation: 2253

Frameworks with xibs connected to viewController require explicit loading from the bundle.

Usually when we create a cocoaTouch UIViewController with xib, this is handled for us. However, when using frameworks, it is not handled.

To solve this, I add load the xib in viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    // Frameworks require loading of the xib to connect xib to view controller
    let bundle = Bundle(for: type(of: self))
    bundle.loadNibNamed("viewControllerName", owner: self, options: nil)
}

Upvotes: 2

drewster
drewster

Reputation: 6090

You need to call your presentNext() after the ViewController has actually appeared -- not in viewDidLoad, and not even in viewWillAppear.

Like this:

class ViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        presentNext()
    }
    @objc func presentNext() {
        let loginVC = LoginVC()
        present(loginVC, animated: true, completion: nil)
    }

}

Here's the working test project:

https://github.com/drewster99/SO_LoginVC

Also, maybe double-check that your ViewController.xib has the IBOutlet actually attached for the button. It's actually got to be that. Everything else looks good.

Here's what I've got:

AppDelegate:

import UIKit

@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 homeViewController = ViewController()
        homeViewController.view.backgroundColor = UIColor.white
        window!.rootViewController = homeViewController
        window!.makeKeyAndVisible()
        return true
    }
}

ViewController.swift:

import UIKit
import LoginFrameworkThing

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton! {
        didSet {
            button.addTarget(self, action: #selector(presentNext), for: .touchUpInside)
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }

    @objc func presentNext() {
        print("Presenting next...")
        let loginVC = LoginVC()
        present(loginVC, animated: true, completion: nil)
    }
}

The button is connected in ViewController, and LoginVC (both .xib and .swift) exist in the framework.

I updated the sample project. Check the link.

Upvotes: 1

Related Questions