Does implementing UIResponder touch methods inside a UIView subclass violate MVC? - ios

The following UIResponder methods report raw touches on screen:
- touchesBegan:withEvent:
- touchesMoved:withEvent:
- touchesEnded:withEvent:
Recently I was playing with a UIView subclass that I wanted to be touch responsive.
Initially I implemented the methods above in the UIViewController that was responsible for the view in question.
However, I realised that the touch methods were being called whenever the UIViewControllers view was being touched, not the subview I wanted.
I reimplemented the methods inside a UIView subclass and everything worked as expected.
However I feel like this is violating MVC. I have control logic inside my view.
Should I keep the methods implemented inside the UIViewController instead, and somehow hit test to interpret which view was touched, or am I correct in having the methods implemented inside the UIView subClass?
I feel like the later is the lazy way out.
Thanks for your time.

In MVC, the view is responsible for user interaction. Therefore, it makes more sense to have your UIResponder methods overridden in your UIView. To keep strictly with MVC, you should then use a delegate pattern (or some other pattern) to call control logic functions that are in your controller.
The above image is from (Apple's MVC documentation). The part that pertains to your question is in the upper left. The view should tell the controller it has been touched ect, and the controller should execute the logic.
The UIViewController only is able to implement these methods because it comes with a built in view. This is confusing because it means that the UIViewController itself violates MVC, but thats a more involved discussion.

Related

UIView subclass with its own controller - Design pattern

As far as i know, to follow MVC pattern guidelines, you shouldn't have controllers inside a view (ie. server requests, delegates, etc.), however some of the Apple's sample codes have animations inside the view (mainly CABasicAnimation instances in order to animate its layer).
My question is if having some controller logic inside your view violates the MVC design pattern, and if so, what's the best alternative, for example if we want a UIView that it will always animate (ie. bounce) when doing some action, and you don't want to implement that logic for each UIViewController that has an instance of the view.
You can simply create a UIViewController that contains the logic of animation of the view, beeing the view owner.
After this you use it like a singleton, and add its view to all the places you want, by having the controller always animating the view.
BUT to answer at your first question, yes it breaks the pattern if you put controller code inside a view.

How to implement interactive transitions in a custom container view controller

I implemented my own custom container view controller and I try to make it compatible with iOS 7 view controller transitions. I make my custom container view controller conform to UIViewControllerContextTransitioning and I send self when I call transitionDuration: and animateTransition:. It all works fine as long as I use only animated transitions.
Now I want to make it work with interactive transitions, so I call the interaction controller's startInteractiveTransition: instead of the animation controller's animateTransition:, using self again as a parameter. However, if I use a UIPercentDrivenInteractiveTransition as the interaction controller, it then calls a _animator method on my context (which is the container view controller itself). Of course, I haven't implemented this method which is private and undocumented, so it crashes...
Am I missing something in my implementation? Is UIPercentDrivenInteractiveTransition only compatible with Apple classes because it uses some implementation magic (as when it requires that everything should be in a UIView animation block)? The documentation and header files make it look like we can implement our own container view controllers and still use custom transitions, but is it really true or just wishful thinking because nobody would actually do that?
If I can't use UIPercentDrivenInteractiveTransition, then where exactly should the interaction/animation logic be? In the UIViewControllerTransitionCoordinatorContext object? In the UIViewControllerInteractiveTransitioning object (most likely, this object is the driver...)? Or in the UIViewControllerAnimatedTransitioning object (this is probably where the real animation should happen, but would that mean calling animateTransition: several times during the interaction? Or adding new methods for each step of the interactive transition?)
Edit: The documentation says:
A percent-driven interactive transition object drives the custom animation between the disappearance of one view controller and the appearance of another. It relies on a transition animator delegate—a custom object that adopts the UIViewControllerAnimatorTransitioning protocol—to set up and perform the animations.
There is no UIViewControllerAnimatorTransitioning protocol. Assuming it is a mistake, or a name change that happened during iOS 7 development and it is actually the UIViewControllerAnimatedTransitioning protocol, how do we link the interaction controller with the animation controller? I guess it's the responsibility of the view controller driving the transition but I don't see any API to make this link, so it would mean that UIPercentDrivenInteractiveTransition is indeed reserved for Apple classes?
I'm trying to do the same on my own and ended up writing my own UIPercentDrivenInteractiveTransition equivalent. Seems like the percent driven transition asks for the animation and actually starts it after the interactive transition is started. I've got some trouble with implementing the reverse animation when canceling though.

UIView without an UIViewController

How and where to call - setNeedsLayout method of an UIView instance when device rotation changes without necessarily having an UIViewController controlling the view? Basically this could boil down to understanding view life cycle generally without a controller...
I guess some of the things that an UIViewController acts on behalf of the views when the user interacts with them (such as interface orientation changes, etc.) might be be handled by registering to UIApplicationDidChangeStatusBarOrientationNotification in UIView instead.

What happens if I write touches event for a View in its View Controller?

I have seen Code snippets where people have written touchesBegan and touchesEnded in the View Controller of a view.
I am relatively new to iOS development and am unable to understand how is that possible.
Aren't these methods of UIView class that we override in our custom views.
and If its possible then If I call view's touches Event which version gets the priority ?
The one in the View controller or one in the View itself.
As you can easily look up in the documentation, the touches...:withEvent: family of methods is declared in the UIResponder class. Since both UIView and UIViewController inherit from UIResponder, both classes have access to the methods and can override them.
As to the question which implementation gets priority if both are implemented, that is defined by the responder chain. Touch events travel up the responder chain until they find an object that wants to handle the event. Since a view is placed before its view controller in the responder chain, the implementation in the view class would be executed.
The view controller has copies of these methods as well. It's for convenience so you don't have to create a custom UIView subclass just to handle touch interaction.
If both the view and the view controller implement these methods then they both get called when the user touches the screen, however I believe that the ones on the view get called first.
Note that as of iOS 3.2/4.0, UIGestureRecognizers are generally a much easier way to do most types of touch interaction. There's rarely any need to use touchesBegan and touchesEnded any more.

To subclass or not to subclass : that is the ...?

I am building an app with many views and subviews.
I am trying to figure out how to approach creation of the subclass.
one simple example:
I have a table view with heads view and footer view. (I have much more complex views then this one, but I am trying to explain my point with a simple one).
In the beginning I didn't want to create views subclasses for every view, but I found that my code is getting complex and hard to navigate in.
Then I found my self creating a view for every subview in the main view. The truth is that I like it better cause my code is clearer to me. Th only thing is that I don't know what are to cons and pros of each approach.
How do you decide when to create a custom view or create it's code in the main view?
Thanks
I usually create a UIView subclass only when there is specific functionality that would be best done in such a class. This might be that the view is a control such as a keyboard to enter a value or a UITableViewCell subclass.
Otherwise I would generally not subclass UIView but just create the view hierarchy in Interface Builder or in code and then use the UIViewController subclass to do all the business logic.
Basically, in general with iOS programming, you want to have all the logic of how a "view" (or screen, or whatever you want to call it) in a UIViewController subclass. It's hard though to really give good advice without fully understanding your hierarchy.

Resources