ios XCTest failed Could not find a storyboard named LaunchScreen in bundle NSBundle - swift

I'm trying to run a simple test case where I want to test my view controller but I'm getting this error
Could not find a storyboard named 'LaunchScreen' in bundle NSBundle
I'm running a cocoapods lib through the example folder
this is my test case:
import XCTest
#testable import Welcome
class WelcomeViewControllerTests: XCTestCase {
var viewModel: WelcomeViewModelProtocol!
var viewController: WelcomeViewController!
override func setUpWithError() throws {
viewModel = WelcomeViewModel()
viewController = WelcomeViewController(viewModel: viewModel)
viewController.viewDidLoad()
}
override func tearDownWithError() throws {
viewModel = nil
viewController = nil
}
func testLoadLaunchScreen() throws {
viewController.loadLaunchScreen()
}
}
This is my viewController:
import UIKit
public class WelcomeViewController: UIViewController {
private var viewModel: WelcomeViewModelProtocol
public override func viewDidLoad() {
super.viewDidLoad()
loadLaunchScreen()
let string = viewModel.fetchExample()
debugPrint(string)
}
public init(viewModel: WelcomeViewModelProtocol) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func loadLaunchScreen() {
let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "LaunchScreen")
navigationController?.isNavigationBarHidden = true
navigationController?.pushViewController(vc, animated: false)
}
}

Related

How to navigate push view controller from UIView in Swift

How to navigate PushViewController from UIView class to New View Controller, Till now what I tried with delegate/ protocol but still no success from button click, below is the swift code what I tried to navigate from uiview class
protocol MyViewDelegate {
func didTapButton()
}
class Ticket : UIView {
static let instance = Ticket()
#IBOutlet var parentView: UIView!
#IBOutlet weak var ticketView: UIView!
var delegate : MyViewDelegate?
override init (frame: CGRect) {
super.init(frame: frame)
Bundle.main.loadNibNamed("Ticket", owner: self, options: nil)
}
#IBAction func btnHistoryTicket(_ sender: ThemeButtonTicket) {
}
#IBAction func btnNewTicket(_ sender: ThemeButtonTicket) {
func buttonTapAction() {
delegate?.didTapButton() // Expect to navigate
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func showTicket(){
UIApplication.shared.windows.first{$0.isKeyWindow}?.addSubview(parentView)
}
}
class ViewController: UIViewController, MyViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let ticket = Ticket()
ticket.delegate = self
}
func didTapButton() {
let vc = kMainStoryboard.instantiateViewController(withIdentifier: "SubmitTicketVC") as! SubmitTicketVC
self.navigationController?.pushViewController(vc, animated: true)
}
}

Updating Inactive Window

How do you update an inactive window?
I have an application with 2 windows. One is for user input and is the main window by default. The second is just to display values in NSTextFields and is generally inactive. I'm having trouble updating elements in the second window.
Here's minimal code which reproduces the problem (Swift 3):
import Cocoa
class ViewController: NSViewController {
#IBOutlet var logArea: NSScrollView!
#IBOutlet var logText: NSTextView!
var windowController: NSWindowController
var vc: ViewController2
#IBAction func runButton(_ sender: Any) {
displayText(text: "Running")
vc.updateInput(value: 1.0005)
}
required init?(coder decoder: NSCoder) {
let storyboard = NSStoryboard(name: "Main",bundle: nil)
windowController = storyboard.instantiateController(withIdentifier: "WindowID") as! NSWindowController
windowController.window?.makeKeyAndOrderFront(nil)
vc = storyboard.instantiateController(withIdentifier: "ViewID") as! ViewController2
vc.loadView()
super.init(coder: decoder)
}
func displayText(text: String) {
logText.textStorage?.append(NSAttributedString(string: text + "\n"))
}
}
class ViewController2: NSViewController {
#IBOutlet var input0: NSTextField!
#IBAction func updateButton(_ sender: Any) {
updateInput(value: 1.0)
}
func updateInput(value: Double) {
if input0.doubleValue == 1.0 { input0.doubleValue = 0.0 }
else { input0.doubleValue = value }
}
}
vc.updateInput(value: 1.0005) in ViewController doesn't work, but updateButton in ViewController2 does.
Any help would be appreciated! Thanks!

Storyboard doesn't contain a view controller with identifier error?

I'm trying to present a programmatically made viewcontroller on a viewcontroller, where I can't figure out how to make ID of such made-up viewcontroller.
As can be seen in the code under, I have a base view controller, 'ViewController' and if I click a button(didTapButton) I want a programmatically made view controller(SecondViewController) show up.
Though I can't set the second view controller's name, that I can't even execute the code -- instantiateViewController(withIdentifier: "SecondController").
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func didTapButton(_ sender: Any) {
let controller = storyboard!.instantiateViewController(withIdentifier: "SecondController")
present(controller, animated: true)
}
}
......
class SecondViewController: UIViewController {
private var customTransitioningDelegate = TransitioningDelegate()
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: "SecondController", bundle: nibBundleOrNil)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
}
How can I set up the second view controller's ID? If it's not what should be done, what else can I try?
instantiateViewController lets you instanciate something that is defined in a given storyboard. So either you name it in the storyboard via xcode or you must do something else. For example, instanciate the object from code, ie let c=SecondViewController() (with appropriate parameters). You are trying to mix different ways to instanciate an object.
You don't need any identifiers for programmatically created vcs just do
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .green
}
}
Use like
#IBAction func didTapButton(_ sender: Any) {
let vc = SecondViewController()
present(vc, animated: true)
}
Edit:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .green
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
let vc2 = SecondViewController()
vc2.providesPresentationContextTransitionStyle = true
vc2.definesPresentationContext = true
vc2.modalPresentationStyle = .overCurrentContext
self.present(vc2, animated: true)
}
}
}
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = UIView()
v.backgroundColor = .red
view.addSubview(v)
v.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
v.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
v.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
v.widthAnchor.constraint(equalToConstant:200),
v.heightAnchor.constraint(equalToConstant:200)
])
}
}

How to declare generic base class?

I have a case which is:
class BaseMvpController<V, P: BasePresenter>: UIViewController { }
I need to make the base class to be of generic type instead of UIViewController.
At some point, I need it to be UIViewController , UITableViewController ..etc
for Example :
My Base Class
class BaseMvpController<V, P: BasePresenter>: UIViewController {
typealias View = V
private(set) var presenter: P!
// MARK: - Initializers
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override public init(nibName: String?, bundle: Bundle?) {
super.init(nibName: nibName, bundle: bundle)
}
deinit {
guard let view = self as? P.View else {return}
if let presenter = presenter {
presenter.detachView(view)
}
}
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
presenter = createPresenter()
}
override func viewWillAppear(_ animated: Bool) {
guard let view = self as? P.View else {
preconditionFailure("MVP ViewController must implement the view protocol `\(View.self)`!")
}
super.viewWillAppear(animated)
if !presenter.isAttached {
presenter.attachView(view)
}
}
// MARK: - MVP
/// Override and return a presenter in a subclass.
func createPresenter() -> P {
preconditionFailure("MVP method `createPresenter()` must be override in a subclass and do not call `super.createPresenter()`!")
}
}
My AController
class AController : BaseMvpController <AView, APresenter> { }
If we thought it was a kind of UIViewController its works normally
My BController
class BController : BaseMvpController <AView, APresenter> { }
If we thought it was a kind of UITableViewController, This is case I can not override numberOfItemInRaw and dequeCell ...etc , because base controller inherit from UIViewController
I want to make Base controller works with all controller (UIViewController, UITableViewController, UICollectionViewController .. etc).
How can i do this
You can 'hide' generic inside another class.
E.g.,
class Generic<T, U> { }
class BV: UIViewController {
var generic: Generic<Int, String>? = nil
}

'UIStoryboard.type' does not have member named 'centerViewController'

I am following THIS tutorial but I didn't downloaded starter project file from that tutorial because I want to make it differently but I am stuck here since an hour because I got this Error:
'UIStoryboard.type' does not have member named 'centerViewController'
Here I am trying to add subView (CenterViewController) into ContainerViewController.
Here is my code for ContainerViewController.swift
import UIKit
import QuartzCore
class ContainerViewController: UIViewController, CenterViewControllerDelegate {
var centerNavigationController: UINavigationController!
var centerViewController: CenterViewController!
override init() {
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
centerViewController = UIStoryboard.centerViewController()
//'UIStoryboard.type' does not have member named 'centerViewController'
centerViewController.delegate = self
// wrap the centerViewController in a navigation controller, so we can push views to it
// and display bar button items in the navigation bar
centerNavigationController = UINavigationController(rootViewController: centerViewController)
view.addSubview(centerNavigationController.view)
addChildViewController(centerNavigationController)
centerNavigationController.didMoveToParentViewController(self)
}
}
This is my CenterViewController.swift
import UIKit
#objc
protocol CenterViewControllerDelegate {
optional func toggleLeftPanel()
optional func collapseSidePanels()
}
class CenterViewController: UIViewController {
var delegate: CenterViewControllerDelegate?
#IBAction func tableTapped(sender: AnyObject) {
}
}
And this is my AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let containerViewController = ContainerViewController()
window!.rootViewController = containerViewController
window!.makeKeyAndVisible()
return true
}
Can anyOne give me any Idea what I am missing?
You are missing the extension the tutorial author has provided that makes the UIStoryboard.centerViewController() method exist. The code is at the bottom of ContainerViewController.swift in his downloadable starter project, and I've copied it down below as well:
private extension UIStoryboard {
class func mainStoryboard() -> UIStoryboard { return UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()) }
class func leftViewController() -> SidePanelViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("LeftViewController") as? SidePanelViewController
}
class func rightViewController() -> SidePanelViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("RightViewController") as? SidePanelViewController
}
class func centerViewController() -> CenterViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("CenterViewController") as? CenterViewController
}
}
Add this to the bottom of your ContainerViewController.swift and it should work. (That is, as long as you have these view controllers set up in the right storyboard files with the right identifiers.)