How to SubView a ViewController into a SubView of another ViewController - ios

I have two ViewController.
One ViewControllers contain a UITableView. And another contains a UIButton.
I have created a SubView Programmatically.Now i want to SubView the ViewController which contains the UITableView in other when i Press UIButton.
I searched all over the net but cannot find any stable solution.
Currently i am trying this:
bodyView =[[UIView alloc]initWithFrame:CGRectMake(0,120,containerView.frame.size.width,120)];
bodyView.backgroundColor = [UIColor redColor];
CustomTableVC *tableVC = [[CustomTableVC alloc]init];
[tableVC willMoveToParentViewController:self];
[bodyView addSubview:tableVC.view];
[self addChildViewController:tableVC];
[tableVC didMoveToParentViewController:self];
[containerView addSubview:bodyView];

You cannot.
You can only use the view property of your UIViewController to assign into UIView associated in your second UIViewController which is not recommended because UIViewController as per MVC pattern holds lot controller stuff which includes populating the view and resolving the inputs/touch, which is an overhead in your (using multiple of viewcontrollers without needed) case.
You need to use one UIViewController. Add UITableView only in it, and UIButton only in it. You only use one controller and multiple views.
The other approach, if you do not want to change your code, may also use ContainerView. But in that case you need to create separate ViewControllers for UIButton and UITableView. And if you want to fetch data inbetween the ViewControllers, that will be a huge pain and also a bad software design with so much coupling and less encapsulation.

i have tried this one and it's working for me.
#IBAction func moveToOther() {
var otherController = OtherViewController()
var bodyView = UIView(frame: CGRectMake(0,120, self.view.frame.size.width, 120))
bodyView.backgroundColor = UIColor.redColor();
bodyView.layer.borderWidth = 1.0
let tblCntrl = UITableViewController()
bodyView.addSubview(tblCntrl.tableView)
bodyView.clipsToBounds = true
otherController.addChildViewController(tblCntrl)
tblCntrl.didMoveToParentViewController(otherController)
otherController.view.addSubview(bodyView)
self.navigationController?.pushViewController(otherController, animated: true)
}

You should use only one view controller that contains both the table view & UIButton.
By default hide the table view.
Just hide the button and show the table view when the button is clicked.

Related

How can I add a common view to multiple ViewControllers in iOS Swift?

I'm kinda new to iOS development.
I want to have a custom View and some Labels inside it. And In some viewControllers of my app on a button click I want to add/show that View
at the bottom of that viewController.
As far as I'm manually adding the view in storyboard in all the viewControllers in which I want the view to display. But this is not efficient. How can I add this view in viewControllers programmatically on button click?
Make one BaseViewController class inherited with UIViewController
Now create method named as designFooter in BaseViewController
func designFooter() {
var viewFooter: UIView = UIView(frame: CGRectMake(0, self.view.bounds.size.height - 50, self.view.bounds.size.width, 50))
viewFooter.backgroundColor = UIColor.redColor()
self.view!.addSubview(viewFooter)
}
For Swift 4, 5.1:
func designFooter() {
let viewFooter: UIView = UIView(frame: CGRect(x:0, y:self.view.bounds.size.height - 50, width:self.view.bounds.size.width, height:50))
viewFooter.backgroundColor = UIColor.red
self.view.addSubview(viewFooter)
}
Now inherit this BaseViewController to you ViewController where you want to add footer, and on button click just call self.designFooter()
If this subview you want to add has some dynamic content or has much of its own logic, you might want to employ view controller containment, specifically not only add a subview, but add a controller associated with that subview, too. So, you can have a scene in your storyboard for this subview that will appear on the bottom, and associate it with its own view controller. Then, when you want to add it, you'd do something like:
let child = storyboard!.instantiateViewController(withIdentifier: "storyboardid")
addChild(child)
// set the `frame` or `constraints` such that it is in the correct place, perhaps animating it into place
view.addSubview(child.view)
child.didMove(toParent: self)
And when you want to remove it:
child.willMove(toParent: nil)
child.view.removeFromSuperview()
removeChild(child)
Personally, if this can really appear and disappear from any scene in my app I actually embed the whole app in a container view controller. Then this popping of the child in and out only has to be done once, on this master container view controller.
For example, consider this storyboard:
That is an embedded "container view" (the storyboard equivalent of view controller containment, discussed above). And I can then have a label animate in an out (by animating layoutIfNeeded after changing the height constraint of some view with a label). Then, this bottom view can animate in and out regardless of which view controller's view is currently visible:
Just create a UIView and call addSubview:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];//change this frame for your purposes
UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(10,10,50,10)];
[l setText: #"My label"];
[view addSubview: l];
[self.view addSubview: view];
As far as adding this to multiple view controllers... I suppose if you had a lot of different view controllers with this same UIView you could create a subclass of UIViewController called CustomViewController. In that class add the above code to viewDidLoad. Then, subclass CustomViewController in all the view controllers with this particular view, and they will automatically add it for you.
Edit:
If you want to design the view in interface builder, make a custom subclass of UIView. Let's call this CustomView. Design it in a nib and add any code you want. Then, whenever you want to create that view, simply call CustomView *cv = [[CustomView alloc] initWithFrame:...] and then do [self.view addSubview:cv];

uitableview inside multiple view controllers

I have to 'repeat' a uitableview into 2 or more view controllers. Like using a uitableviewcontroller with its methods inside view controllers using the methods/delegates/datasources from the uitablewviewcontroller.
Example: I've a uitableviewcontroller wich displays a twitter feed with its own style, so I need this table in more than 1 view controller and maybe just changing the twitteruser in each view controller (just an example).
TRY: What I've done is to create (with storyboard) a uiviewcontroller and a uitablewviewcontroller, both with their own methods. And on uiviewcontroller viewdidload, try to add the uitablewviewcontroller.tableview as a subclass. and this works! But the result is an empty table. I tried to set the delegates/datasources but it ddnt work..
-(void)viewDidLoad
{
[super viewDidLoad];
//Add Table as subview
thetable *t = [[thetable alloc] init];
[self.view addSubview:t.tableView];
t.tableView.frame = CGRectMake(0, 100, 320, 2000);
t.tableView.backgroundColor = [UIColor blueColor];
}
This code works, but just displays an empty uitable inside the view controller..
*thetable is a uitableviewcontroller object (.h, .m, and storyboard view)
*Just set the backgroundcolor to check if there's anything on screen
*using ios6
Thanks!
Make sure you are implementing the table view delegate and datasource methods in thetable.Also try [t.tableView reloadData] after adding the tableView to the view controller's view.

Manage uiview and uiviewcontroller

I created an uiview , that contained , many textfields , and I have an uiviewcontroller with xib file responsible for making signature .Is it possible to add this viewcontroller to my uiview in order to have this componant of drawing signature in the footer of my uiview ??
- (void)init { //parent view
...
FooterViewController *fvc = [[FooterViewController alloc] initWithNibName:#"myNibName" bundle:nil];
[self addSubview: fvc.view];
fvc.view.origin = CGPointMake(0, self.frame.size.height - fvc.view.frame.size.height);
}
this is how you can create your viewController from xib file and add its view to the main view. assuming this is what you are trying to do.
If you are using storyboards, the easiest way to go is to drag a Container View object from the Object library (where buttons, labels, etc. are) to your view controller's view. This will create a child view controller that you can handle separately and that will be already resized to mirror the size of the container view controller.

Using static cells without a UITableViewController [duplicate]

I'm using XCode 4.2 and have built my UI using Storyboards. I need to create a view that has content above and below a UITableView and I can achieve this by using a UIViewController. A UITableViewController does not let you add content above or below the table. You can use the table header/footer but that doesn't work for what I would like to achieve.
I now have a UIViewController with a UITableView embedded in it. I can adjust the height and width of the UITableView accordingly which provides me the UI layout that I am looking for.
I can customize the static cells in the UITableView but when I try to build I get the following error:
Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances
My question is how are others getting around this? Creating a tableview with static cells and laying them out visually is very nice but apparently that is not allowed for some reason that I cannot understand. I can't switch to a UITableViewController because of my visual layout requirements.
Any assistance would be greatly appreciated.
You can achieve this in Xcode 4.5 and later versions, assuming your app is targeted at iOS 6+.
In the Storyboard simply create a UIViewController with a View Container inside it's main view. Then hook up that View Container to a UITableViewController that contains static cells.
Just like this:
You don't need a single line of code. Just control click, drag and select embed. The view controller containment is handled for you.
You are right. In storyboard, you cannot have a tableView with static cells embedded in a viewController. One way around it (I have not tried it myself, though, so I am not sure if it works) can be that you create an instance of UITableViewController in storyboard with static cells. Add an instance of UIView to your viewController, and then programmatically load the tableView of the UITableViewController into the UIView of your viewController.
pmd's answer works but in the event that backward compatibility with iOS 5 is required as well, you can do the embedding programatically using the View Containment API.
In the viewDidLoad method of your parent UIViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
MyTableViewController* vc =[storyboard instantiateViewControllerWithIdentifier:#"MyTableVC"];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
// ensure embedded view is aligned to top
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
vc.view.frame = frame;
[vc didMoveToParentViewController:self];
}
Don't forget to specify a storyboard ID for your UITableViewController with the static cells.
I know this is an old question but I have a scrappy solution to this issue.
I needed 3 static cells on a UIViewController so this is what I did:
Drag in some Table View Cells into your interface (not into UITableView) - add text and whatever else you need.
Make IBOutlet properties for your cells and synthesise them.
Drag a button and make it cover the entire cell. Set the button to type 'Custom' so it appears invisible - repeat for all cells
Add numeric tags to your buttons
Implement the following functions. buttonDown is connected to the buttons 'Touch Down' event. buttonUp is connected to 'Touch Up Inside' AND 'Touch Up Outside'
-(IBAction)buttonDown:(id)sender {
if ([sender tag] == 1) {
myFirstCell.selected = YES;
}
else if ([sender tag] == 2) {
mySecondCell.selected = YES;
}
else if ([sender tag] == 3) {
myThirdCell.selected = YES;
}
}
-(IBAction)buttonUp:(id)sender {
myFirstCell.selected = NO;
mySecondCell.selected = NO;
myThirdCell.selected = NO;
}
You can do whatever else you like in the buttonDown event and use the button to go directly to a new view. I find this pretty useful.
I am not sure what you mean by static cells, but if you are trying to build the cells in IB, and then want to use it in your tableView, what you could do is in your cellForRowAtIndex you can call loadNibNamed passing the name of the .nib file you created for the cells as the parameter. Make sure that you have an outlet in your viewController which maps to the cell's .nib. Try exploring in these directions if that's what you are trying to achieve
You can make it dynamic and then switch of scrolling:
[yourTableName setScrollEnabled:NO];

UIView in UITabBar don't extend to full

I have a UIViewController called DashBoardViewController that acts as delegate for a UITabBar. In its xib I have placed a UITabBar with 3 UITabBarItem.
Each of these items activate a different View Controller, let's call them ViewController1, ViewController2, ViewController3
DashBoardViewController is supposed to show ViewController1 and select the first bar on loading, so in my initWithNibName I have what follows:
...
ViewController1* vc = [[ViewController1 alloc] initWithNibName:#"ViewController1" bundle:nil];
[self.view addSubview:vc.view];
self.currentViewController = vc;
...
I implement the UITabBarDelegate having something as follows:
if (item == viewController1Item) {
ViewController2 *vc2 = [self.childrenControllers objectAtIndex:1];
[self.currentViewController.view removeFromSuperview];
[self.view addSubview:vc2.view];
self.currentViewController = vc2;
} ...
Problem
The View Controller in the first UITabBarItem always works as expected, extending it to the full size of thew view.
However, in the second and following tabs, this doesn't happen: the view doesn't extends. This shows if, for example, I align a tab with the bottom in the ViewController2 XIB: this will not be at the bottom when viewed inside the UITabBarItem.
Note
Please note that this is not related to the XIB: if I invert ViewController1 and ViewController2, it will be ViewController1 the one failing to extend. It's related to the UITabBarItem.
Ideas
Possibly, this depends by the way I addSubview when I call the DashBoardViewController's initWithNibName. But I can't find a way to explain this.
Other details
All the XIB are set with "Size = none".
I can't really speak to the way you have your XIB setup without seeing it, but I can make a couple of suggestions.
The behaviour that you're trying to implement by removing & adding subviews to DashBoardViewController should really be handled by a UITabBarController. This provides a UITabBar, a view for your content and handles the logic of switching between UIViewControllers while keeping layout sane and being part of the SDK.
If for some reason you can't, or don't want to use a UITabBarController, I'd suggest implementing a viewWillLayoutSubviews method on your DashBoardViewController, like so:
- (void)viewWillLayoutSubviews
{
if( self.currentViewController )
{
self.currentViewController.view.frame = self.view.bounds;
}
}
Maybe also try adding the self.currentViewController.view.frame = self.view.bounds; line after you've swapped ViewControllers too, for good measure. This will make sure that the frame of your current ViewController's view is always sized to fill the bounds of DashBoardViewController's view.
This isn't the 'Proper' way to do it though, I'd really recommend using a UITabBarController if you can, since you don't know how much else of UITabBarController you'll end up re-implementing if you start rolling your own controller.
Any further problems will most probably be to do with the internal layout of your sub-ViewControllers, rather than their size / position in DashBoardViewController's view.
On your XIB File make sure that your set the flexible height to stick to top and bottom, this way the UITableView will always have the same height as the 4" display

Resources