Make view controller in run time with xibs - ios

I want to make view controller at run time with the nib name like this,
But this is being crashed.
Error
[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key imageViewApp.
let vc = UIViewController(nibName: nibName, bundle: nil)
When I try with the static values like this
let vc = MyViewController(nibName: "MyViewController", bundle: nil), it is working.
This is the IBOutlet in MyViewController
I googled it but haven't found enough solution please let me know the solution.

You're initializing a UIViewController and UIViewController has no imageViewApp property. You need to initialize your own subclass where you define that property, as you do in your second example.
Try something like this:
let vc = MyViewController(nibName: nibName, bundle: nil)
If your nib file has the same name as your class, you don't have to specify it:
let vc = MyViewController(nibName: nil, bundle: nil)

Remove imageViewApp property IBOutlet from that view controller and give that ImageView a tag and access it with the tag.

Related

UIViewController xib file containing a collectionview with a custom cell

I have a xib file containing an UIViewController called FullScreenGalleryVC. It contains a UICollectionView that contains a custom UICollectionViewCell, which identifier is fullscreen_cell.
When I want to create a new FullScreenGalleryVC, I call FullscreenGalleryVC.display(from: self).
Here's the func:
class func display(from sourcevc:UIViewController){
let vc=UINib(nibName: "FullscreenGalleryVC", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! FullscreenGalleryVC
sourcevc.present(vc, animated: true, completion: nil)
}
I get this error:
could not dequeue a view of kind: UICollectionElementKindCell with
identifier fullscreen_cell - must register a nib or a class for the
identifier or connect a prototype cell in a storyboard
It works fine if I put the custom cell in another xib file and call register(nibClass, forCellWithReuseIdentifier: cellId).
It works fine if I don't put this FullScreenGalleryVC class in a separate xib file (and keep it in my main storyboard).
But I use this class from both the app and an action extension so that's why I'd like to use a common file instead of duplicating everything. Is there a way to do that or do I imperatively have to put the custom cell in a different xib file to make it work?
If you a xib file for FullScreenGalleryVC controller then you should use register(nibClass, forCellWithReuseIdentifier: cellId) to tell the collection view how to create a new cell of the given type.
let cellNib = UINib(nibName: "FullScreenGalleryCell", bundle: .main)
collectionView.register(cellNib, forCellWithReuseIdentifier: "fullscreen_cell")
If you use a storyboard, then it's already known to the collection view with the specified cellId.
In my opinion, you can use a storyboard for FullScreenGalleryVC and reuse the same for other classes.
Present a viewController from a specific storyboard like,
let storyboard = UIStoryboard(name: "YourStoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "storyboardId")
self.present(controller, animated: true, completion: nil)

How to use init for view controller loaded from storyboard?

I always initialise my view controllers from the storyboard like this:
let controller = storyboard!.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController
I want to initialise variables on init. Usually I just assign them to the controller like controller.variable = x. I'd prefer to use the init() function, but it seems I can't if I use the storyboard. What's the best way to do this?
I don't think so it will be useful if you create own init() for ViewController.
You can simply use like below:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
controller.pageTitle = "XYZ"
controller.pageNumber = 2
If you want to pass multiple values to the destination controller, then you can pass the model class as well if all the values define a category class.

How to Open Multiple Xibs with the same method?

I have configured my UIView using Nib's .So, I just want to pass the name of nib in a method and it will open the particular ViewController.
For opening a particular UIView made with Xib, I have done it like this
func presentMyViewControllerNib(){
let controller = MyViewController(nibName: "MyViewController", bundle: nil)
let navigationController = UINavigationController(rootViewController: controller)
let currentController = getCurrentViewController()
currentController!.present(navigationController, animated: false, completion: nil)
getCurrentViewController here is just fetching the viewcontroller displayed.
So, i just want a method like this func presentGeneralisedNib(nibName:String) in which I pass the name of my Xib.
I think it's not possible but if someone can help.

(lldb) po self.storyboard nil

How/when can a UIViewController return self.storyboard nil.
I am trying to instantiate a ViewController with:
self.storyboard!.instantiateViewControllerWithIdentifier
But self.storyboard is nil?
Note: the plist is set to the right storyboard.
Per the Apple documentation, UIViewController's storyboard property represents the storyboard from which the view controller originated. It returns an optional UIStoryboard instance which is nil if the view controller was not instantiated from a storyboard.
Try this :
let localStoryboard = UIStoryboard(name: "Main", bundle: nil)

can not instantiate a view controller, swift, ios

I am trying to instantiate a view controller from the nib file like following :
class TNAChallengerHandler:ChallengeHandler {
var controller : ViewController
// Default initializer
init(realm iRealm: String, controller iController : ViewController) {
println("Default initializers")
self.controller = iController;
super.init(realm: iRealm)
}
// Convience initializer
convenience init() {
println("Convience initializers")
let vc = ViewController(nibName: "ViewController", bundle: nil)
self.init(realm: "SingleStepAuthRealm", controller:vc)
}
Executing the codes and I am getting
iOS_SingleBasedAdapterAuthentication[40828:5708548] *** Terminating app due to uncaught
exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/tonytran/Library/Developer/CoreSimulator/Devices/6B797313-635F-4ABD-B3C6-A1D9DF3F1E85/
data/Containers/Bundle/Application/FDC3FD2B-6E26-4654-AC0F-ED3F44DDC5F6/iOS_SingleBasedAdapterAuthentication.app> (loaded)' with name 'ViewController''
I double check in the storyboard, the custom class of the class is already changed to ViewController like below and the name is as same as ViewController.swift
Any thoughts about this. All comments are welcomed here.
You don't have a nib file named ViewController.
You have a storyboard. A storyboard is compiled into a set of nib files, but you don't access those nib files directly. Instead, you need to give your view controller a Storyboard ID. Then you can ask the storyboard to instantiate that view controller.
Let's say you use “GetData” as the Storyboard ID:
and I assume your storyboard is named Main.storyboard. Then you can instantiate the view controller like this:
convenience init() {
println("Convenience initializers")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("GetData")
self.init(realm: "SingleStepAuthRealm", controller: vc)
}
That said, I'm not sure it makes a lot of sense to instantiate a view controller by name when that view controller is also used as the root view controller of a UINavigationController. Are you sure you want to instantiate a new view controller here?

Resources