Is there an alternative way to show UIView instead of using .XIB? Because I have many UIViewControllers that I was showing it as presentView and now I have to change it.
My Code:
#IBAction func basketClearButton(sender: UITapGestureRecognizer) {
let basketClearView = UIStoryboard(name:"Main", bundle: nil).instantiateViewControllerWithIdentifier("clearBasket") as! ClearBasketViewController
//self.presentViewController(alert, animated: true, completion: nil)
self.view.addSubview(basketClearView)
}
you can make those view controllers child of the VC you want to present them on here, by making one view controller child of another, you can add view of child VC as a subview to the view of parent VC
in that way you can show them on the same screen and whole of your previous code will stay as it is, only presenting logic will change
This can also be helpful tutorial
Anything you can do in a .xib file, you can also do in code. So, if you have a view controller whose view you wish to add to the display without creating a .xib file for it, you can simply edit the view's content programmatically (for example, [self.view addSubview:someImageViewYouCreated];).
In the main view controller (or any other view controller in which you want to display the other view's content, you can just add the view from the new view controller. If, for example, the view controller you wish to add to the display is called SecondViewController, you'd write:
SecondViewController *newView = [[SecondViewController alloc] init];
[self.view addSubview:newView.view];
If you want to add the view with a fade in animation, you can do something like this:
newView.view.alpha = 0.0;
[UIView animateWithDuration:0.3f animations:^{
newView.view.alpha = 1.0;
}];
Related
I added child view controller to parent view controller programmatically in swift 3.0.
But I do not want the child view controller width as full screen, I want to customise the width and height of the child view controller. I tried to open the custom size child view controller, but it is not working.
// Here is my code
let secondViewController = storyboard.instantiateViewController(withIdentifier: storyBoardName)
secondViewController.modalPresentationStyle = UIModalPresentationStyle.custom
secondViewController.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width-500, height: self.view.bounds.height)
self.present(secondViewController, animated: false, completion: nil)
Is there a way to achieve this?
In your code, you are not adding the secondViewController as childview controller. You are presenting that view controller. There is a difference.
You are trying to use UIModalPresentationStyle.custom to present viewcontroller using custom style. But using this custom style is not this trivial.
From documentation:
Creating a custom style involves
subclassing UIPresentationController and using its methods to animate
any custom view onto the screen and to set the size and position of
the presented view controller. The presentation controller also
handles any adaptations that occur because of changes to the presented
view controller’s traits
It tells you that you need to subclass UIPresentationController and subclass its method(with other methods) - (CGRect)frameOfPresentedViewInContainerView to set the frame of the presented viewcontroller.
More is explained in this link.
You can ofcourse achieve all this by actually adding a childviewcontroller.
Steps would be like this:
Create your child viewcontroller instance.
Set its view frame to whatever you want.
Add its view as a subview on to parent view controller's view using addSubview:
Call [addChildViewController] on parent viewcontrller (https://developer.apple.com/documentation/uikit/uiviewcontroller/1621394-addchildviewcontroller)
It depends on what you're trying to do, when I want to show some UI on top of another UIViewController I usually use a fullscreen view controller with self.modalPresentationStyle = .overFullScreen. Then I create another view which has the visible size I actually want to show to the user. This allows you to do pretty much anything you want.
But if you want an actual child viewcontroller, you need to use the appropriate functions for it.
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.
I have a UIViewController (called A), but sometimes I need to show a second UIViewController (called B) , cause I dont wanna disturb the UI actions in A( A still need to respond to some touch actions ), so is there any methods to show B in non-modal way?
Try this :
[self addChildViewController:viewControllerB];
[self.view addSubview:viewControllerB.view];
You can easily embed any viewcontroller in another. check it out:
iOS Nested View Controllers view inside UIViewController's view?
You can embed B in A as a child view.
For an exhaustive description see http://subjective-objective-c.blogspot.co.uk/2011/08/writing-high-quality-view-controller.html, for a simple demo, check out this code: https://github.com/toolmanGitHub/stackedViewControllers
Here's how you can display a view controller in a non-modal way in Swift:
let newController = RegisterController()
self.addChildViewController(newController)
self.view.addSubview(newController.view)
Remove view in a non-modal way:
view.removeFromSuperview()
I guess you are talking about presenting view controllers modally in iPhone. In iPad, just for the sake of completeness in the example, you have more ways to show a view controller modally that doesn't fill the whole screen.
You can use UIViewController containment for this.
All in all it's just adding a view controller as a child of another while adding it's view to the hierarchy.
Check this tutorial at obj.io. This is what #Justafinger is suggesting but complete instead as #Justafinger forgot some important calls.
You can
addChildViewController
like this -
- (void)loadContentView
{
CGFloat ht = 0; // height you want to change;
HomeAdsTVC_iPhone *vc1 = [[HomeAdsTVC_iPhone alloc] init];
[self addChildViewController:vc1];
CGRect frame = self.view.bounds;
frame.origin.y = ht;
frame.size.height -= ht;
vc1.view.frame = self.view.bounds;
[self.view addSubview:vc1.view];
[vc1 didMoveToParentViewController:self];
}
Since there is no complete, definitive answer to this common recurring question, I'll ask and answer it here.
Often we need to present a UIViewController such that it doesn't cover full screen, as in the picture below.
Apple provides several similar UIViewController, such as UIAlertView, Twitter or Facebook share view controller, etc..
How can we achieve this effect for a custom controller?
NOTE : This solution is broken in iOS 8. I will post new solution ASAP.
I am going to answer here using storyboard but it is also possible without storyboard.
Init: Create two UIViewController in storyboard.
lets say FirstViewController which is normal and SecondViewController which will be the popup.
Modal Segue: Put UIButton in FirstViewController and create a segue on this UIButton to SecondViewController as modal segue.
Make Transparent: Now select UIView (UIView Which is created by default with UIViewController) of SecondViewController and change its background color to clear color.
Make background Dim: Add an UIImageView in SecondViewController which covers whole screen and sets its image to some dimmed semi transparent image. You can get a sample from here : UIAlertView Background Image
Display Design: Now add an UIView and make any kind of design you want to show. Here is a screenshot of my storyboard
Here I have add segue on login button which open SecondViewController as popup to ask username and password
Important: Now that main step. We want that SecondViewController doesn't hide FirstViewController completely. We have set clear color but this is not enough. By default it adds black behind model presentation so we have to add one line of code in viewDidLoad of FirstViewController. You can add it at another place also but it should run before segue.
[self setModalPresentationStyle:UIModalPresentationCurrentContext];
Dismiss: When to dismiss depends on your use case. This is a modal presentation so to dismiss we do what we do for modal presentation:
[self dismissViewControllerAnimated:YES completion:Nil];
Thats all.....
Any kind of suggestion and comment are welcome.
Demo :
You can get demo source project from Here : Popup Demo
NEW : Someone have done very nice job on this concept : MZFormSheetController
New : I found one more code to get this kind of function : KLCPopup
iOS 8 Update : I made this method to work with both iOS 7 and iOS 8
+ (void)setPresentationStyleForSelfController:(UIViewController *)selfController presentingController:(UIViewController *)presentingController
{
if (iOSVersion >= 8.0)
{
presentingController.providesPresentationContextTransitionStyle = YES;
presentingController.definesPresentationContext = YES;
[presentingController setModalPresentationStyle:UIModalPresentationOverCurrentContext];
}
else
{
[selfController setModalPresentationStyle:UIModalPresentationCurrentContext];
[selfController.navigationController setModalPresentationStyle:UIModalPresentationCurrentContext];
}
}
Can use this method inside prepareForSegue deligate like this
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
PopUpViewController *popup = segue.destinationViewController;
[self setPresentationStyleForSelfController:self presentingController:popup]
}
Modal Popups in Interface Builder (Storyboards)
Step 1
On the ViewController you want as your modal popup, make the background color of the root UIView clear.
Tip: Do not use the root UIView as your popup. Add a new UIView that is smaller to be your popup.
Step 2
Create a Segue to the ViewController that has your popup. Select "Present Modally".
Two Methods To Create Popup From Here
Method One - Using the Segue
Select the Segue and change Presentation to "Over Current Context":
Method Two - Using the View Controller
Select the ViewController Scene that is your popup. In Attributes Inspector, under View Controller section, set Presentation to "Over Current Context":
Either method will work. That should do it!
You can do this in Interface Builder.
For the view you wish to present modally set its outermost view background to transparent
Control + click and drag from the host view controller to the modal view controller
Select present modally
Click on the newly created segue and in the Attribute Inspector (on the right) set "Presentation" to "Over Current Context"
Feel free to use my form sheet controller MZFormSheetControllerfor iPhone, in example project there are many examples on how to present modal view controller which will not cover full window and has many presentation/transition styles.
You can also try newest version of MZFormSheetController which is called MZFormSheetPresentationController and have a lot of more features.
You can use EzPopup (https://github.com/huynguyencong/EzPopup), it is a Swift pod and very easy to use:
// init YourViewController
let contentVC = ...
// Init popup view controller with content is your content view controller
let popupVC = PopupViewController(contentController: contentVC, popupWidth: 100, popupHeight: 200)
// show it by call present(_ , animated:) method from a current UIViewController
present(popupVC, animated: true)
Imao put UIImageView on background is not the best idea . In my case i added on controller view other 2 views . First view has [UIColor clearColor] on background, second - color which u want to be transparent (grey in my case).Note that order is important.Then for second view set alpha 0.5(alpha >=0 <=1).Added this to lines in prepareForSegue
infoVC.providesPresentationContextTransitionStyle = YES;
infoVC.definesPresentationContext = YES;
And thats all.
Swift 4:
To add an overlay, or the popup view
You can also use the Container View with which you get a free View Controller ( you get the Container View from the usual object palette/library)
Steps:
Have a View (ViewForContainer in the pic) that holds this Container View, to dim it when the contents of Container View are displayed. Connect the outlet inside the first View Controller
Hide this View when 1st VC loads
Unhide when Button is clicked
To dim this View when the Container View content is displayed, set the Views Background to Black and opacity to 30%
You will get this effect when you click on the Button
You can do this to add any other subview to the view controller.
First set the status bar to None for the ViewController which you want to add as subview so that you can resize to whatever you want. Then create a button in Present View controller and a method for button click. In the method:
- (IBAction)btnLogin:(id)sender {
SubView *sub = [[SubView alloc] initWithNibName:#"SubView" bundle:nil];
sub.view.frame = CGRectMake(20, 100, sub.view.frame.size.width, sub.view.frame.size.height);
[self.view addSubview:sub.view];
}
Hope this helps, feel free to ask if any queries...
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