Reuse childs from custom UIVIewController using storyboard - ios

I have a storyboard with a navigation controller that leads to an UIVIewController that I want to reuse. That UIVIewController has a ParentUIViewController that has all the basic functionalities for all the UIVIewControllers that I am reusing.
Currently I am copying and pasting (meh) and then I change the class of the UIViewController to the ChildUIVIewController that I want to use (ChildUIViewController extends ParentUIViewController).
But this sounds like a bad solution. Everytime I want to change the ParentViewController visually I need to update, manually, all other ChildViewControllers.
I have tried to create a xib for the ParentViewController but the xib isn't loaded because I need a xib with the name of the ChildViewController. I have created it and then said the class is the ParentViewController but it crashes in the segue.
EDIT
I have created an example of the status of my problem
https://github.com/tiagoalmeida/storyboardexample
Note that the ParentViewController has a set of logic way more complicated that is not illustrated there. Also note that I am also using a TableView. I hope that this can illustrate the problem.

Keep the logic on the parentViewController and the UI Part on the child UIViewControllers. If you need to create a new UIViewController, you will create a child that will have a corresponding XIB (or get rid of XIBs and create the interface by hand).

Have you considered looping back into the same UIViewController via a "phantom button"?
Have a look at this: UIStoryboard Power Drill, Batteries included
Essentially you can drag a Bar Button Item into the little black bar under the View Controller in Storyboard (the 1 with View Controller, First Responder, and Exit icons; sorry, I don't recall what this is called exactly), then you can control+drag from that button back into the UIViewController for a Push segue. This should create a loop segue in your Storyboard. All you need to do next is give that segue an identifier, programmatically call it from your code using [self performSegueWithIdentifier:], then implement -(void)prepareForSegue: and use [segue destinationViewController] to conditionally set the title and perhaps some flags so you can identify when to use different kinds of fetches (or other code variations) in the same Class code.

Related

Reusing the same viewController on top of the navigationStack in swift

For my app project i have created a tableView that show a wine including, rating reviews, tasting notes and all sorts of data in each section. In the last section the user is shown two similar wines, once pushed it is the purpose to reUse the current viewController, and throw it onto the navigation stack as the user might browse another wine inside that viewController and so forth.
How would you go about, reUsing the same viewController. Since building infinite numbers of the same viewController in storyboards seems abit rookie to me. Thanks all help appreciated.
You can use Storyboards and reuse the ViewController with no problem.
In the Storyboard use the Storyboard ID in the identity inspector, Add a unique ID to the ViewController.
After that it's pretty simple, you can ether:
Instantiate the first level viewController with the segue, than once you want to add another ViewController (of the same type) with the UIStoryboard instantiateviewcontrollerwithidentifier: and give the unique id of the ViewController, and present it
or
You can just use the UIStoryboard instantiateviewcontrollerwithidentifier: every time you want to present the ViewController
If you want to use storyboard, there is a hack (a bit dirty).
You should add button to view controller. But not to the view of
view controller, you should add it to the top section (top bar) of
your view controller.
Then you add segue from this button to this very view controller.
Now you may use this segue from code (performSegue...)

Using storyboarding in xCode how can I change the value of a label from a different view?

I'm writing an app that uses storyboarding and I want to update the labels in one view by clicking a button in a previous view.
_label.text = variable1;
is the line I would use to change the value of label, which is in the next view, when I click the button. Using this method I can easily change labels in the same view as the button but it does nothing when I go to the next view and see empty labels.
I've tried looking everywhere and found similar issues but couldn't find anything that worked for me so any solution would be very appreciated!
Unfortunately, it is not possible to connect IBOutlets between different scenes in storyboard.
It is difficult to suggest some precise solution because you have to provide more details about the setup which you have. Still, it is possible to outline some possible solutions:
Using prepareForSegue
If the view controller which you want to modify appears after the segue is performed you can customise its appearance in prepareForSegue function.
Using delegation
You can assign the view controller which wants to modify another view controller as its delegate. For example, if ViewController1 wants to modify ViewController2:
#interface ViewController1: UIViewController {}
#property (nonatomic,weak) ViewController2 *controllerThatIWantToModify;
with such setup you can call:
self.controllerThatIWantToModify.label.text = variable1;
You use storyboards, so there must be a segue from your first viewController (with the button) to your second (with labels in it).
If it is the case, you can set up the labels of the second view controller from the prepareForSegue method of your first view controller.
This method is called with a segue object which has a destinationViewController property which is your second view controller.
If you have several segue from this viewController, you should check if it is the right segue and then set it up.
To do that you need to set up outlets that gives you access to the labels from the viewController.
Then you can either write a setUpLabelsWith:(NSString)text1 ... method in your view controller, or directly access the outlets from the first view controller (supposing their are not private).
Yes this supposes your second view controller has a custom class.

Component reuse within Storyboard

I am new to iOS development, with a couple of years of Android experience. I started directly with XCode 5 and the Storyboard paradigm. I like the visual approach to sketching out the flow of an app, but IMHO, it does not really force component reuse, or maybe I do not know how to do it.
I have an actual problem, which is the following: Instead of the typical master-detail approach, I have a situation, in which clicking on a TableView cell forces a push to another TableView, which looks the same and behaves the same way. There are two specific types of a TableViewCell that I want to reuse across the whole application, so I can't just duplicate the first TableViewController several times. I need changes in one type of TableViewCell to be affected everywhere, same for the look and behaviour of the Tableview. Sort of like reusing a component, you get the picture I hope.
I tried creating a custom TableView and TableViewCell in a separate xib file, connecting it to a custom controller class. Yet, when I want to reuse that controller class in the storyboard, I can't make a segue from the cell to the next one, because only view controllers are displayed, but no views inside.
Maybe, I am doing it all wrong. Perhaps, I should make a single controller, and force it to seque to itself if possible, no idea.
What would you do?
You can do programatic Segue from the didselected.....
#import "someVC.h"
Then when you want to Segue to the new VC
// Create a VC and remember to set the Storyboard ID of someVC (example someVCID)
someVC *newView = [self.storyboard instantiateViewControllerWithIdentifier:#"someVCID"];
// Can't remember how this works but you can change the Transition method
// newView.modalTransitionStyle = UIModalTransition;
// If you want to pass data, setup someArray in the someVC .h with #property (nonatomic, strong) NSArray *someArray;
newView.someArray = MyLocalArray;
// Animated or not
[self presentViewController:newView animated:NO completion:nil];
If what you're trying to do is performing a segue on the same UITableView you can check this answer by Rob
I'll report what it contains for completeness:
If you're using dynamic cell prototypes, you obviously can do a segue
from the table view cell to the controller without any problem.
When you make your segue, you end up with:
But let's imagine for a second that there's some reason that doesn't
work for you, e.g. you could not have a segue from the cell (for
example, you need to invoke segue from didSelectRowAtIndexPath, not
upon selecting the cell). In this case, you couldn't use that previous
technique.
There are a couple of options in this case:
As pointed out by Chris, if only supporting iOS 6 and above, use the above technique, but (a) make sure your
didSelectRowAtIndexPath uses self for the sender and then have
shouldPerformSegueWithIdentifier only allow the segue if the sender
== self (thus when the sender is the table view cell, it will be canceled);
Perhaps even easier, just don't define a segue at all and have your didSelectRowAtIndexPath manually
instantiateViewControllerWithIdentifier and then push/present
that view controller as appropriate; or
You can use the following, kludgy work-around: In short, add a button to your view controller (drag it down to the bar at the
bottom), where it won't show up on the view, but you can use its
segues. So first, drag the rounded button to the controller's bar at
the bottom of the scene:
Now you can make a segue from that button to your view controller:
And thus, you end up with the self-referential segue again:
You must give that segue an identifier, so you can invoke it
programmatically via performSegueWithIdentifier, but it works. Not
the most elegant of solutions, but I think it's better than having an
extra scene on your storyboard.
None of these are ideal, but you have lots of options.
well.. in iOs think about it differently, if i were you i would create multiple ViewController, even if they're almost the same, and create a custom cell class, and make this cell take a configuration block.
Now for each ViewController (( or TableViewController )), you reuse your same custom UITableViewCell and just pass it what's slightly different for each case, and moreover you can also create a BaseTableViewController that will have the general configuration, and in each ViewController pass the custom changes you need.
Think about it, when you look at your storyboard you'll be able to see all your workflow, and when something goes wrong you'll be able to debug, if you have are gonna use what you suggested, debugging will be a real pain i imagine.
Anyway, try it out, and ask more if you need further clarification.

Storyboards, UITabBarController and SWRevealViewController

I have a storyboard that uses a UITabBarController with 3 tabs.
I want to use SWRevealViewController to add the sliding menu functionality.
Opening the menu will slide the hole UITabBarController.
Did anyone managed to implement this kind of behaviour with storyboards UITabBarController and SWRevealViewController?
Thank you
Managed to integrate it. Below are the steps to do it:
Add a new UIViewController to the storyboard.
Remove the content view from the newly added UIViewController
Make sure "Is Initial View Controller" is checked in IB for the newly added UIViewController
Set the custom class for the newly added UIViewController to SWRevealViewController
Connect it to a view controller that you intend to be the rear view controller - give the segue "sw_rear" identifier in IB. This must be a reveal controller segue type.
Connect it to the UITabBarController - give the segue "sw_front" identifier in IB. This must be a reveal controller segue type.
You should use a navigation controller before tab bar controller(sw_front > navigation controller > tab bar controller).
gfdx answered his own question, but make sure to also look at this tutorial for more insight on how to hook up everything else correctly.
Because I'm using Core Data and I was told that calling
[[NSApp delegate]managedObjectContext];
is not a good idea, I pass in my data controller class to the views in AppDelegate.m. Since I'm now using the SWRevealViewController instead of my subclass of UITabBarController, I had to make some modifications.
SWRevealViewController performs some interesting behaviors on load, one of which is loading the dependent view controllers by calling the segues. Be aware that if you make changes in your subclassed prepareForSegue:sender: method, make sure to always, always call the super's method, otherwise you'll end up with a black, blank application.

Refactoring a UITableViewController subclass to a UIViewController subclass

In my app, I wanted to show a table in the "full screen," so I created a subclass of UITableViewController. When I want to show the table, I just instantiate it and use pushViewController:animated:. Now I've decided that I actually want to show it as a modal, so I want to give it a navigation bar with a "Done" button. I believe this means that I now need to make this a UIViewController subclass instead of a UITableViewController subclass, since it will now be more than just a table. I'm not really sure if this is something that can be done, though; I've created an xib, but Xcode doesn't seem to want to let me use that xib to create IBOutlets in the .h file, so I don't think the two are "connected."
I ran into this problem once before and worked around it by just creating a new UIViewController subclass and xib and just copy-and-pasting all the stuff I needed from the UITableViewController subclass's files into the new subclass's files. I knew then as I know now that that was a hacky and unpleasant solution, though. Does anyone know how something like this can be done properly?
Also, to avoid this problem in the future, should I just never make top-level views like this in the future and just make sure everything I use pushViewController:animated: or presentModalViewController:animated: with is a UIViewController subclass? Or is it safe to do what I've been doing?
Several things you mention in your question indicate some misunderstandings. First, if you're pushing you table view controller, then it has to be embedded in a navigation controller, and thus will have a navigation bar -- you can add a done button to this bar, if that's all you're trying to change. No need to refactor your code.
If you want to use a UIViewController instead of a table view controller, you should be able to hook up your nib. Did you change the class of the files owner in the nib to your UIViewController class? After you do that, you should be able to hook up the outlets.
There's nothing "hacky" about copying and pasting code from a table view controller into a view controller. I do this all the time, rather than writing out all those files.
I'm not sure what you're asking in the last question. How you get your table view on the screen (pushing or presenting) has nothing to do with whether what you're showing is a table view controller or a view controller. You should use the one that best fits your needs.

Resources