View/Screen/Activity navigation in MVP - mvp

When using MVP, where should the logic of navigation be stored? Is it in View or is it in the Presenter?
Say View1 (backed by a presenter Presenter1) has a button PushMeToGo somewhere in its view hierarchy. Said button should move the user from View1 to View2 when pressed.
Should the logic of moving into View2 be handled directly inside View1 or should it notify its presenter which will then execute the command instead?

This question was asked here 5 years ago: In MVP, who should handle navigation? . Just let me make a little contribution. A view should be as dummy as possible containing no business logic at all (except of direct user interaction or, let's say, animation). Thus, the View1.PushMeToGo button could simply fire an event to notify the Presenter1 that this button is pressed, and let the presenter delegate the navigation request to whatever that's responsible for navigatigating between views (let the presenter be as clean as possible). The V->P notification mechanism is on your own: an event bus, a simple observer, a single handler notified via Presenter1.onPushMeToGoClicked that's defined in the presenter interface as well. If you unit-test your code, this also lets you test the onPushMeToGoClicked handler having dummy views.

Related

OS X gesture and the responder chain

I have a window with a content view that does several things, including managing an iOS like navigation controller.
The window's content view front most view is an invisible custom view set here to manage drag n drop all over the window, called DragNDropView.
Now I want to manage the swipe gesture to navigate (left swipe only) in the navigation controller.
Unfortunately the DragNDropView catches the gesture (if I implement -(void)swipeWithEvent: and set acceptTouchEvents:YES on it), and I don't want that since I want the views behind it to catch it, so of course I set acceptTouchEvents to NO on the DragNDropView.
I'm suprised the gesture event does not "go down" the view hierarchy as the views below do have their acceptTouchEvents set to YES when the front most view has acceptTouchEvents set to NO.
If the front most view does not handle the gesture, the gesture event is not passed to the views behind it????
gestures handling seems to be in NSResponder, so I even expect my NSViewController subclass to handle it, but it seems I can't.
Can any one help me understanding the problem?

Click events getting routed to the wrong view

I have a window with two views in it:
Both the movie view and the controller view override mouseDown: and mouseUp:, for different purposes (the movie view has a target and action and reacts as a button, whereas the controller seeks and supports dragging).
The twist is, when I click within the movie view—which, as shown in the screenshot, will generally be large enough to make missing it and hitting the controller view instead wildly improbable—the mouseDown: and mouseUp: messages are sent to the controller view! The movie view never receives either message.
I have not overridden hitTest: in the movie view or in its parent view (which is a plain NSView), only in the controller view (for reasons that have to do with a tracking area I have on that view—my implementation simply returns self, which is the controller view).
So, what gives?
Well, you probably guessed it: It was my hitTest: implementation in the controller view.
It turns out that hitTest: is not only sent to the views whose frames the mouse location lies within; it is sent to every view in the window, even views that were nowhere near the mouse at either end of the click.
So, when overriding hitTest:, make sure that you verify that the point is actually within yourself. The simplest way is to send [super hitTest:thePoint] and only do your custom hit-test if the result is not nil. (Unless you want to steal clicks from other views in the window.)

Cocoa objective-c, is there an equivalent to PHP sessions?

My app lets the user create multiple custom views by clicking a button (the views are simple circles). When they mouseDown on the circle I send a message to the NotificationCenter and run Core Animation to make the view pulse (fade in and out). I also set NSView *activeView to the view passed to the NotificationCenter.
In the background of these user created views is a custom view named gameMap. If a user clicks outside of one of the circles then gameMap sends a message to the NotificationCenter.
What should happen here is the activeView (circle) should move to the mouse click point. But because the NotificationCenter is in my AppController class, if it is being notified of a click outside of a circle view it doesn't have an activeView to reference.
I need a way to store, independent of classes, the activeView. In PHP I would just use a $_SESSION['activeView'] = $thisView, or something similar. Can I do something like this in cocoa?

Update NSView in function of events

I have a main view (subclass of NSView) and as i'm new to cocoa, i'd like to know how to update the view in function of events.
I know there are many methods that take events such as -(void)mouseMoved:(NSEvent*)event or - (void)mouseClicked:(NSEvent*)event My algorithm to determine what to do is ready. I want to know where I should update the main view: is it in the -(void)mouseMoved:(NSEvent*)event or in the - (void)drawRect:(NSRect)dirtyRect. And if it is in drawRect, then how should i pass the information to it?
Thanks in advance!
Here's a quick explanation that will hopefully get you on your way:
Handle events
User actions are communicated to your views and windows by events (keyboard + mouse) and actions (events interpreted by buttons and other controls). Your views should react to these events and actions by updating the model, which are the lower-level data structures that represent whatever your program displays to the user. If Cocoa, the view typically communicates through a controller object to make changes to the model.
Invalidate display / trigger redraw
After you have updated your model, you need to inform the view that it needs to redraw. This can be done in several ways, but the simplest way to do it is -setNeedsDisplay:YES. This will ensure that at some point in the immediate future, your view will redraw itself to display the updated model data.
Draw
At some point Cocoa will call -drawRect: on your view. Inside -drawRect:, you should read the requisite data from your model and draw the necessary graphics. You shouldn't do any manipulation of the model in this method.

How to make a view controller first responder for an NSView in Cocoa

I'm trying to implement a view controller for a custom NSOpenGLView based view (this is Cocoa, not Cocoa Touch).
The view is contained within a NIB loaded window but it does not have its own NIB. In fact the window contains multiple instances of the view.
I want to route mouse events to the controller instead of to the view. I would like for this to happen as soon as the user clicks within the corresponding view.
So how can this be done ?
I've tried having the view's becomeFirstResponder method call makeFirstResponder with the controller as argument. However that doesn't seem to work, the view still receives the mouse events instead of the controller if NSView::becomeFirstResponder returns YES. If it returns NO then neither of my classes receive the mouse events.
Of course I could implement the mouse event handling methods in the view and explicitly forward them to the controller but it seems like there should be a better way to handle this.
For general "first responder" status, I recommend Charles Parnot's MTViewController, an NSViewController subclass that uses KVO to make certain the controller is in the responder chain with no extra effort on your part.
However, in your case, you want mouse events too. There's really no way around this - your view will need to translate mouse events into controller interactions.

Resources