edit: I want to make this view independent to be reusable.
The question explains itself. I have searched, but didn't find any answers, even if the question seems to be common.
I have two view controllers VC1 and VC2. My code is like:
VC1.present(VC2, animated: true)
Then, I need my VC2 to totally ignore all touches and pass them through.
Good example is AppStore rating success alert (attached). You can scroll even when alert is presented, I need the same behavior.
You should use an UIView and just overlay it over your VC1. Then the VC1 stays scrollable even when the UIView is presented
Related
I'm implementing a solution whereas I've got a parent UIViewController in which presents a UIPageViewController modally in viewDidAppear(). UIPageViewController enables sliding between 3 viewcontrollers, whereas the center one has the backgroundColor set to UIColor.clear so that I can see the first and parent VC through it. This works great, apart from the fact that I can't interact with it.
What I've tried:
Setting the user interaction enabled property to false for the empty (placeholder) viewcontroller
Presenting the pageVC with .overCurrentContext as style
Presenting the pageVC by adding it as a child viewcontroller to the parent
Looked into overriding some methods, but I'm not sure how to implement this
The idea to solve it was to either have the overlaying views to ignore their touch events, but later it may seem like an idea to have them delegate or somehow send the touch events further back in the view hierarchy.
Nevertheless, I can't figure it out and was hoping if any of you could help me out. Thanks a lot!
Let's say we have a CustomNavigationController that subclass UINavigationController.
Let's use the following example to explain the question.
CustomNavC -> pushes on VC A. From VC A you can push on 2 different VC's. VC B and VC C. We'll say both these VC's push on various other VC's, further down the rabbit hole.
Now, let's say we want to show a UIView that acts as a banner view appearing directly underneath the navigation controller. However, we only want the banner to show on say VC A, VC C, VC E, VC J, etc.
Is there any possible way to do this from the CustomNavC itself? Or is the only way to gain this control of which VC's show the banner... is to put it on the VC's itself?
1) We put it on the CustomNavC view. When the user moves from a VC to a VC that both show the banner (A->C), we want to same banner to remain. We gain this by laying out the banner on the CustomNavC. However, how can we check whether a VC should be displaying the banner or not? Every time the NavC pushes or pops a VC, we would have to check. Likely some function on each VC like -(BOOL)allowBannerViewDisplay and VC's can opt in.
2) If we put the BannerView on individual VC's, it becomes a bit easier but the deal breaker is that if we move from VC A -> VC C, the user is going to see 2 separate banners during the transition instead of the same banner.
So, we need to solve it way 1. The CustomNavC listens for a notification and displays the banner. It would then need to check the currently displaying VC and only display the banner if the VC allowed it. However, if the user transitions to another VC, it needs to recheck the logic of whether the banner is currently displaying and if it is, check if that VC wants it to display.
All of this feels weird to me.
Suggestions?
I've never implemented something like this, but off the bat my thought is this:
Set up this custom view as a new class, and pass the reference along your VCs. Set up a method on the custom View as a class method that takes in a UIViewController and returns a bool for whether or not it should be displayed (rather than on each of your VCs). This class method can get the class and see if it exists in an array of class names or something.
Now, I've never moved a UIView from one VC to another, but I think it's possible to remove the UIView as a subview from the VC it's on, and place it on the new one as a subview.
Alternatively, perhaps you could have a datasource/delegate object for this custom view, and create a new custom UIView on each VC as needed that all reference the same datasource / delegate to set up the state appropriately.
UIPopoverController has a .isVisible property to tell if the popover is on the screen or not.
Is there an equivalent for the new UIPopoverPresentationController?
It's a UIPresentationController, so it has a presentedView, so you can ask whether that presentedView has a non-nil window.
But the real answer is that you are looking completely in the wrong place. UIPopoverPresentationController is nothing like the old UIPopoverController; they have almost nothing in common and they are not managed in similar ways. A popover is now just a presented view controller. Concentrate on the view controller. You just dismiss it, like any presented view controller (self.dismissViewController...). This is the whole point. You no longer retain a reference to anything; you no longer have to manage anything; it's just like presenting and dismissing any modal dialog / view.
Just a question I've been pondering, 'traditionally' with modal viewcontrollers the presenting 'parent' view controller should dismiss the presented child.
Apple have stated that the presented child should not self dismiss, thus I tend to set up a delegate protocol just to dismiss a modal view controller.
This seems somewhat overkill,
I was wondering since objective C passes by reference anyway, and there wouldn't be a performance cost, couldn't I just pass a reference of the presenting parent viewcontroller to the modally presented child viewcontroller during instantiation and then make a method call back to the parent to dismiss the child?
Sorry if this is a stupid question...
The reason why you typically setup the delegate/protocol for something like this is that it makes your code much less coupled. Say you wanted to present your view as a popover or subview later? You may not think this is needed but it may as the project grows.
Since the parent controller handles its own modals, subviews, and popovers it knows what to do when a button to exit is pressed (or some other action). The modal (in this case) does not necessarily (and shouldn't!) know how it is being presented, hence it should tell its delegate that and let that controller handle it (popViewController, dismissViewController, removeSubview, etc...). This is a large part of understanding OOP and will help keep your code cleaner.
And no, this is not a stupid question in my opinion.
What is the difference beetween calling presentModalViewController and pushViewController, when :
animation is set to NO (even if yes, that's just an animation style that can be changed).
a navigation controller is defined when presenting the modal view, so it can be navigable too, with a call stack, ....
Is this just to be able to go back from the first pushed view ? Woooaaaaaa.....
I guess the difference is elsewhere and deeper. No ?
Ignoring transitions/animations and how things are structured behind the scenes (which aleph_null's alswer provides a good discussion of), the only user-facing difference is the ability to return to the preceding view automatically using the navigation bar.
If you use pushViewController you will automatically get a "Back" button in the navigation bar. If you use presentModalViewController you do not, and generally will have to implement your own controls and/or callbacks to handle dismissing the controller.
Conceptually the modal presentation style is generally used for atomic tasks that you cannot navigate away from (i.e. you either complete the task, or you cancel, and you cannot do anything else within the app until you do one or the other).
If you're wondering why have the difference in the first place, I can't say. Personally I think frameworks that provide a unified API for moving from one controller to another (like cocos2d, or Android) make a lot more sense.
The most important difference is about semantics. Modal view controllers typically indicate that the user has to provide some information or do something. This link explains it more in depth: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
Here's another, less abstract difference they talk about:
"When you present a modal view controller, the system creates a parent-child relationship between the view controller that did the presenting and the view controller that was presented. Specifically, the view controller that did the presenting updates its modalViewController property to point to its presented (child) view controller. Similarly, the presented view controller updates its parentViewController property to point back to the view controller that presented it."
Also see this thread: why "present modal view controller"?
Take a look into the viewControllers in the image
The top 2 viewControllers(login & submit) at the top left are disconnected from the tabBarController & NavigationController
The rest of the viewControllers are embedded in a NavigationController. They somehow belong to the natural flow of the app.
Now you have to ask yourself
Do I need to always show login + submit page every time? It would be pain in the neck for the user to each time go to login even if they logged in last time. These 2 screen really don't fit the natural flow of the screens. So what do we do? We just add them modally using presentViewController
However for the rest of the viewControllers we want to keep them inside 2 navigation so we can easily go back and forth so we use pushViewController
For more information I recommend you to see this video
The image was also picked from this great answer. It's worthy of a look.
This is what my experience says,if you want to manage a hierarchy of views,better go for pushViewController in the navigation controller. It works like a stack of view-controllers in the navigation controller. If however the requirement is just to show a view on executing some actions on the parent view controller then the best way is presenting it modally.
If you need a complex push pop logic always prefer a pushViewController.
UINavigationController are used when you want to have some sort of hierarchal representation of your data (ie drill down). They work using a stack of UIViewController subclasses. Every time you “drill down”, you simply add another view controller to the stack. Then, the “back” logic is simply a matter of popping view controllers off of a stack.
You can check out this link:
http://www.icodeblog.com/2011/10/11/back-to-basics-an-introduction-to-view-controllers/