I have an iOS application with a subview, as well as a UISegmentedControl. I want to use my UISC to change subview1 to subview2. I decided to drag out a few more ViewControllers onto my storyboard, and put subview1 into the first, and subview2 in the second. After connecting the ViewControllers and making outlets for the subviews, I went back to my main ViewController (at this point there are three) and did
#import "SecondViewController"
SecondViewController *myView;
self.mySubview = myView.myOtherSubview;
but the subview on-screen didn't change. Is my template method of doing this totally wrong? If so, how would you suggest I proceed?
Look at [UIView transitionFromView:toView...]
The basic idea is you'll have to child view controllers (check the docs in UIViewController under the child view controllers section) and transition from the view of one to the view of the other.
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html#//apple_ref/occ/clm/UIView/transitionFromView:toView:duration:options:completion:
This question, IOS Storyboard: Load Multiple Subviews for given position, is the same as mine, phrased better. The answer given there worked.
Related
I have a horizontal scrollview with pagination enabled so each page will show a distinct xib view. Some xib views have buttons in them that linked to IBAction. I declare the IBAction in each xib's class. Everything seems and looks good the buttons show clicking effects and all, but the IBAction isn't fired?
Here is a code sample:
let clockView: ClockViewController = ClockViewController(nibName: "ClockViewController", bundle: nil)
let carView: CarViewController = CarViewController(nibName: "CarViewController", bundle: nil)
scrollview.addSubview(clockView.view)
carView.view.frame.origin.x = self.view.frame.width
scrollview.addSubview(carView.view)
clockView and carView both have buttons in them and the buttons are linked to IBActions declared in ClockViewController.swift and CarViewController.swift respectively.
Here how one of the views look like. I'm not adding UIViewController in the xib, I'm only using a UIView. I'm guessing this could be part of the problem but I can't use UIViewController as subview because it gave an error.
Any help is appreciated,
The problem is that you are declaring carView as a local variable, so it will be released once the function exits as there is nothing to hold a strong reference. The view elements themselves are referenced by the scrollview, so they aren't released but there will no longer be a view controller instance to process the events.
If you change carView and clockView to be properties then a strong reference will be held.
The issue seems that you are using ViewControllers inside ViewControllers. If you'd like to do this via storyboard, you'll have to use a containerView and place the ViewController within this containerView using the embed segue that it comes with.
If you'd like to do this programmatically, you'll have to add child viewcontrollers to the parent viewcontroller that emcompasses these child View Controllers that you have which are carView and clockView.
P.S. it's a bit confusing that you are calling your view controller carView, perhaps CarViewController is less confusing :)
I know there is the common practice in iOS development of having one UIViewController presented on the screen whose view is loaded from a XIB which will contain all the UIView subclasses in it.
While I was working on a pretty complex widget for an app, I decided to make the widget subclass a UIViewController instead of a UIView. This was because I thought a UIViewController was essentially a UIView with some helper methods around it. Then I could create a XIB for it (I know UIViews can have their own XIBs too), load the views it contains, place ITS view in the presented parent VC's view, and lay it out.
This works fine so far, but I'm wondering if this is bad practice and if I should just subclass a UIView instead and give it a normal NSObject controller. I am seeing some problems with this and I was wondering if anybody could address concerns I have with this approach?
EDIT NOTE: The widget VC does NOT relate to the VC view it is in and is reusable on ANY screen. So the answer is not subclassing the widget VC with the parent VC. The widget is INSIDE the parent VC, but it is NOT a parent VC.
EDIT NOTE 2: I am NOT using Storyboard. Only Autolayout, XIBs, and ARC.
Why can't we have VC's in VC's?
1) Can VC's be simply dropped into ANOTHER VC's XIB and be loaded easily as a subview?
2) I read here: When to use a UIView vs. a UIViewController on the iPhone?
The top answer explains how the VC controls rotation of the screen and laying out the subviews again, so if you add another VC, then the system will automatically think that THAT is the main VC and will attempt to rotate it instead, causing problems. Is this true? Or is he just talking about if you somehow got into a state where 2 VC's were "presented"? I wasn't sure if his answer applied to VC views that were SUBVIEWS of other VC views.
3) In general is this good practice? It certainly seemed more reasonable as it made loading the subview VC's view much easier.
Thanks!
It's absolutely fine. The answer to your problem is ContainerView.
Container View defines a region within a view controller's view subgraph that can include a child view controller. Create an embed segue from the container view to the child view controller in the storyboard.
You almost got it right. Yes, it's good to make a view controller for what you needed. But you shouldn't just add it's view to the parent view, you should also add the view controller as a child view controller of the first view.
You can add many views controllers as child view controllers of a view controller.
You can learn more about this here.
I have specific situation for which I haven't found solution.
I'm doing over storyboard. So I have ViewController on which I'm using segment control for switching subviews. Every subview is ViewController but one of them is using table view. So basically it's like this:
HomeViewController
FavoritesViewController
Table View (with custom cell)
GalleryViewController
How to properly set up this? Should I rename/refunction FavoritesViewController to FavoritesTableViewController or?
If there is any other question, please ask it.
UPDATE 1:
FavoritesViewController is having just UIView in UI because I don't need whole UIViewController
Create an IBAction from the segmented control. Inside the handling method, use "ViewController containment" to switch between two view controllers.
I am testing out something I would like to have in my app. I have a UiViewController in a storyboard that has a UIScrollView - I now want to add other viewControllers to this scrollView and swipe between them.
I would like to add a view that I made in the storyboard into this UIScrollView. Is it possible?
I tried something along the lines of:
MYViewController *viewOne = [self.storyboard instantiateViewControllerWithIdentifier:#"myView"];
[self.scrollView addSubview:viewOne.view];
I've set the the scrollView size to be bigger than the screen and when the main view loads, I can see there is a scroll view (the scroll bars show) but my viewController is not inside it.
Anyone have any ideas?
The code you posted is still not right, on a couple of levels.
First, you should not use alloc/init for view controllers. You either need to use initWithNibName:bundle: (to create a view controller from a nib file) or instantiateViewControllerWithIdentifier: to load a view controller from a storyboard.
Second, you should not add a view controller's view as a subview of another view controller unless you use the parent/child view controller support that was added in iOS 5 and greatly improved in iOS 6. If you do what you are doing then all sorts of things won't work correctly: Auto-rotation, low memory warnings, background notifications etc. The list of things that can go wrong is unbounded.
The easiest way to do this is to add a container view as a frame to hold your child view controller, and then control-drag from your container view onto the scene that you want to set up as a child. This causes IB to set up and "Embed" segue. Embed segues do all the housekeeping you need to host one view controller's content inside another, with no code needed.
You could create a container view inside your scroll view's content view, and then it would just work fine.
I found the problem:
I was not allocating and initialising my viewController. Ooops.
This is the correct code:
BaseViewController *viewOne = [[BaseViewController alloc]init];
viewOne = [self.storyboard instantiateViewControllerWithIdentifier:#"myView"];
[self.scrollView addSubview:viewOne.view];
In complex screens (View Controllers) I used to separate the whole thing in smaller pieces (I call them widgets). These widgets consist basically of a MyWidget.h and a MyWidget.m file as well as a MyWidget.xib file, where the root element is a UIView and the MyWidget class is the File Owner of the UIView. In the init of this widget I do a loadNibNamed.
In my View Controller I then do a [[MyWidget alloc] init], which I add to View's Controller main view as a sub view. This, so far, works perfectly.
I'm now wondering, how to do the same with storyboard, because I cannot really start to drag in a UIView somewhere, I always have to start with an UIViewController, which I don't want to.
If there is no possible way doing this with a Storyboard, can I simply do it the old way, by using the Storyboard for my main screens and segues, and use a separate .xib file to define custom views?
Putting the widget/view in a separate .xib file works, and is appropriate especially if you might want to reference that same view from multiple View Controllers.
However, sometimes you do want to see the additional view/widget within the same storyboard, and it is possible. Here's how you do it:
Select your view controller in IB (click on the black bar below the view), then drag a UIView from the Object Library into the black bar:
When a view is in the black bar, it's instantiated like any other view in IB but just isn't added to your view hierarchy until you do so in code. Change the view's class to match your own subclass if necessary:
You can hook it up to your view controller like you would hook up any other view:
The added view shows up in your Document Outline and you can hook up actions and references there too:
Now, the problem that remains is that you can't actually see the view no matter how many times you try to click or double click, which would defeat the whole purpose of putting it in the same storyboard. Fortunately there are two workarounds that I know of.
The first workaround is to drag the view from the black bar back into your view controller's view, edit it, then drag it back into the black bar once you're done. This is troublesome but reliable.
The other workaround is more finicky, but I prefer it because it lets me see all my views at the same time:
Drag a UITableView from the Object Library into your newly added view.
Then drag a UITableViewCell into that UITableView.
Once you do that, your view pops out magically by the side, but you have a UITableView that you don't want. You can either resize that to 0x0, or you can delete it and your UIView will (usually) still stay visible.
Occasionally the secondary view will become hidden again in IB. You can repeat the above steps if you deleted the UITableView, or if the UITableView is still in the hierarchy you just need to click on the UITableViewCell and the view will appear again.
The second method works for UIViews but not so well for UIToolbars and is impossible for UIButtons, so the cleanest solution I've found when you need to include lots of different subviews is to attach a single secondary UIView to your view controller as a container that never gets shown, put all your secondary views in there, and use the UITableViewCell trick to make everything visible. I resize my dummy UITableView to 0x0 to make that invisible. Here's a screenshot of how it all looks like together:
If you're just looking to make your view controllers else-where(and not in your story-board), then there's a pretty simple way to accomplish this:
1) Create your CustomViewControllers(abcdController in the code I tried) with their individual xibs as usual.
2) Add a UIViewController(or whatever was the superclass of your CustomViewController) to the story-board.
3) Set the CustomClass to CustomViewController instead of UIViewController as shown here:
4) Finally, in your viewDidLoad, load the custom xib and you're done.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSBundle mainBundle] loadNibNamed:#"abcdController" owner:self options:nil];
// Do any additional setup after loading the view from its nib.
}
I think you can do something like this to get instance of specific viewcontroller from Storyboard and use view on top of it.
ex:
MyViewController* myViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"myViewController"];
UIView* view = myViewController.view; //Get the view from your StoryBoard.
Hope this helps
Thanks
Vijay