UIStoryboard loadNibNamed analog method - ios

I use this tutorial to achieve my custom UITabBarController: link
But I use storyboard instead of xibs. So some of method use this code below:
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"TabBarView" owner:self options:nil];
It is fair for xib but as I think not for storyboard.

This will work for u
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"StoryboardName" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:#"ViewControllerName"];
Dont forget to give identifier to your viewcontroller inside the storyboard.
Note:- Make sure you have given ViewControllerWithIdentifier in storyboard.

I'm afraid storyboards are not well suited for this kind of task. There is no method for getting a specific view from a UIStoryboard instance.
In this case, I would recommend you to create a separate xib file with just the view you want to load on its own and use the code you gave to load it.
On a side note I would also not recommend using a library which has 3 years since the last commit, specially with iOS 7 out which breaks a lot of things.

Related

Unit Testing Initialising storyboard

There are quite a few resources on unit testing whether just purely logical or application level, I am currently working trying to test a UITableViewCell that has IBOutlets within a storyboard and as a few posts have confirmed if i wish to instantiate the storyboard and then the view controller that contains the cell. So you have to go through a few steps to make sure the storyboard and following elements load properly with their IBOutlets like so
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.vc = [storyboard instantiateViewControllerWithIdentifier:#"testTableViewController"];
[self.vc performSelectorOnMainThread:#selector(loadView) withObject:nil waitUntilDone:YES];
followed by this code to get a UITableViewCell from the UITableViewController
[self.vc setTableViewData:#[#1].mutableCopy];
[self.vc.tableView reloadData];
[self.vc.tableView layoutIfNeeded];
SUT = [self.vc.tableView dequeueReusableCellWithIdentifier:#"More Menu Cell"
forIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
and this produces a cell however for me the first breakpoint i have inside the system under test, seems to indicate that the IBOutlets have loaded, however when i actually go to assert anything, they all of a sudden disappear one me...
either references are disappearing for no reason or I'm doing something wrong.
So I have made a few discoveries which i will share here, one of them was a solution to my issue whereas originally this question was one small symptom I was attempting to fix of a larger problem.
The larger problem was, I was testing some UITableViewCells, but unfortunately their IBOutlets which where connected from the storyboard where always nil, which led me to attempt messing with how the system under test should be initialised.
I also found mixed results for using [self.vc performSelectorOnMainThread:#selector(loadView) withObject:nil waitUntilDone:YES]; as sometimes i would still have to call view or viewDidLoad for it to initialise properly. So then i did away with it entirely nd just call view and it seems to work fine.
However my cells still had nil outlets, despite my changes above. After rummaging around the internet a bit i discovered that, you should only be using [self.tableView registerClass:[MyTableViewCell class]forCellReuseIdentifier:#"MytableViewcell"]; if it hasent been created created in a storyboard as a prototype cell. It looks like it already does this for you and attempting to do it again breaks the IBOutlets.
Another small discovery was attempting to test a UIViewController of mine by setting it up like such
MyViewController *SUT = [MyViewController new];
[SUT view];
now although this initialises, again there seems to be some missing steps since this class exists in the storyboard, therefore i recommend the following
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SUT = [storyboard instantiateViewControllerWithIdentifier:#"My Table VC"];
[SUT view];

Difference between instantiateViewControllerWithIdentifier and initWithNibName?

What is the difference between instantiateViewControllerWithIdentifier and initWithNibName, other than former is from storyboard and later is not?
UIStoryboard *signupStory = [UIStoryboard storyboardWithName:#"SignupStory" bundle:[NSBundle mainBundle]];
SignupLoginViewController *signUpVC = [signupStory instantiateViewControllerWithIdentifier:#"SignupVC"];
and
SignupLoginViewController *signUpVC = [[SignupLoginViewController alloc] initWithNibName:#"SignupLoginViewController" bundle:[NSBundle mainBundle]];
If you've created your UI using storyboards, you'll want to call instantiateViewControllerWithIdentifier. Here, the identifier is not part of the view controller itself but is only used by the storyboard to locate the view controller. The storyboard will handle initialization and eventually call initWithCoder, which is why you need to override this when creating subclassed view controllers.
On the other hand, if your UI resides in a pure .xib file - developers generally use initWithNibName. It does, technically, break encapsulation and there are other ways to do it, but you'll see this used most often as it's the designated initializer for the class.

how to know which `Storyboard` is loaded in memory

My Question is simple.
I am using say 5 different storyboards along with 5 different core data models. Now in the app delegate I want to know which storyboard is loaded in memory so that I can set the models accordingly.
I am setting the storyboard under the deployment info in the project settings.
Try appDelegate.window.rootViewController.storyboard.
Try these lines of code...
NSString *mainStoryboard = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"UIMainStoryboardFile"];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:mainStoryboard bundle:nil];
Do they help?

Using storyboard only for certain view controllers

I have done a separate project using storyboard.
I need to integrate with an existing big project which doesn't use storyboard.
Is it possible to use storyboard partly (only for some view controllers)? If so how ?
Sure. You can instantiate separate view controllers from storyboard:
Getting a Storyboard Object
+ storyboardWithName:bundle:
Instantiating Storyboard View Controllers
– instantiateInitialViewController
– instantiateViewControllerWithIdentifier:
For ex:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
YourViewController *yourVC = [storyboard instantiateViewControllerWithIdentifier:#"yourViewControllerIdentifier"];
Yes. It is possible. Any view controllers that aren't on the storyboard are presented in exactly the same way they were in the old projected, by instantiating, setting properties (if need be), and pushing.

How do I use Storyboard in creating an iOS Titanium module?

Does anyone have any examples? I've created iOS and Android modules for Titanium but haven't found any examples where people use Storyboard for visuals.
I know you can load nibs in modules using initWithNibName, check this SO answer out.
For storyboards specifically, I think that gets complicated since Storyboards define a whole navigation structure. I think you have two options, break down the specific windows in the storyboard into nib files, and then load those as needed, or open up the storyboard itself using code similar to this:
// You have to get the resource bundle first
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"YourStoryBoards" bundle:resourceBundle];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"yourViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
I have not tried this out, but I think the key is supplying the correct resource bundle, and then opening from a modal.

Resources