PureMVC Architects Lounge

PureMVC Manifold => Standard Version => Topic started by: adrienl on December 19, 2009, 09:46:42

Title: Linking UI element and Mediator
Post by: adrienl on December 19, 2009, 09:46:42

I have a small begginer problem at starting point on my application :

I have an UI element which is an UIView. It is set as the viewComponent of a Mediator in my StartUpCommand. When the user performs an Event such as a touch on an element of the UI Element, I'd like to launch a notification to inform the Application Engine. I don't know how to proceed from there :
Do I have to set a listener in the mediator or do I have to launch the notification from the UIView itself ?
And how can I do it simply ? I feel I'm missing the point here but I couldn't figure it out by myself so any help would be greatly appreciated :)


Title: Re: Linking UI element and Mediator
Post by: puremvc on December 20, 2009, 11:32:00
I'm hoping Brian will dive in here with some clarification if I go seriously astray with this, but I decided to respond to this Q as an exercise.

Disclaimer: I know absolutely nothing about Objective C. At all.

I am testing the theory that by knowing PureMVC and having an already known demo ported to study, I should be able to begin understanding things about an unfamiliar language rather quickly.

Fortunately Brian has ported the original Flex Employee Admin Demo1 to the iPhone2, and even though the form factor is somewhat different, he has done an admirable job of keeping the actors and collaborations the same. So even though ObjectiveC looks pretty strange to me, I spent about 20 minutes looking through the code (and googling to find out the details of Objective C protocols and view controller delegates) here's what I gleaned:

Firstly, it appears that events as we know them in AS3 do not exist. Instead, what is used is a 'View-Controller Delegate'. This allows the view to talk to its controller, whatever it may be. The view component is given a reference to its delegate in order to communicate with the rest of the system. Surprise! This turns out to be your PureMVC Mediator. The Mediator must therefore not only act as a classic PureMVC Mediator, but also expose a set of methods for the component to invoke when it needs to communicate with the system (in lieu of dispatching events). So...

UserForm.h defines a UserFormViewControllerDelegate protocol which defines the properties and methods to be exposed by said delegate.


Note the statements:
-(void)createUserSelected:(UserVO *)userVO;
-(void)updateUserSelected:(UserVO *)userVO;
-(void)userRolesSelected:(UserVO *)userVO;

In a way, these are defining your 'events' by way of declaring the methods that this component's delegate must expose. Your mediator ends up implementing these methods in the same way AS3 would implement event listeners.

UserForm.m defines a UserForm implementation. This is your view component.

Notice lines for instance in the saveUser method:

if (mode == NEW) {
[delegate createUserSelected:userVO];
} else if (mode == EDIT) {
[delegate updateUserSelected:userVO];

These are 'dispatching' the 'events' (i.e. calling the methods on its ViewControllerDelegate, which ends up being your Mediator).

UserFormMediator.h declares the interface for UserFormMediator.

Notice the angle brackets specifying UserFormMediator adopt the protocol declared in UserFormViewControllerDelegate.

@interface UserFormMediator : Mediator <UserFormViewControllerDelegate> {
This says that UserFormMediator will subclass Mediator, but will also implement UserFormViewControllerDelegate's interface.

UserFormMediator.m defines the implementation for the UserFormMediator


Notice that in its onRegister method, the view component is given a reference to its delegate, the mediator:

-(void)onRegister {
self.viewComponent.delegate = self;

Also notice it implements the methods defined in the UserFormViewControllerDelegate:

-(void)createUserSelected:(UserVO *)userVO {
[self sendNotification:CreateUser body:userVO];

-(void)updateUserSelected:(UserVO *)userVO {
[self sendNotification:UpdateUser body:userVO];

So when the UserForm does:

[delegate createUserSelected:userVO];
This method is called on your UserFormMediator
-(void)createUserSelected:(UserVO *)userVO {
[self sendNotification:CreateUser body:userVO];

So, for those aware of the best practices for PureMVC, the first thing you'll probably say is: 'whoah! view components aren't supposed to know about their Mediators! Giving the view component a reference to the Mediator breaks this practice into tiny pieces and jumps up and down on them doesn't it?

Actually no. No where in the definition of UserForm is UserFormMediator referenced. It is given an instance of some object that implements UserFormViewControllerDelegate. It knows only about the protocol exposed by that object; specifically the methods that we would otherwise implement as event handlers. Mediator specific things like 'handleNotification' or 'onRemove' can't be reached.

The ViewControllerDelegate protocol is essentially declaring: 'these are the things you can say to the system' through me. In AS3 we would say these things by dispatching events, which would be listened for and end up invoking these same methods in the Mediator.

IMHO, it's actually sort of nice to see the formalization of the communications protocol from the view component to the mediator done in this way. In fact it immediately makes me think that for FlashLite versions where there are no Events, this would be quite a nice pattern to implement when using PureMVC.


1AS3/Flex Employee Admin Demo: http://trac.puremvc.org/Demo_AS3_Flex_EmployeeAdmin
2Objective C/UIKit Employee Admin Demo: http://trac.puremvc.orgDemo_ObjectiveC_UIKit_EmployeeAdmin

Title: Re: Linking UI element and Mediator
Post by: uncleunvoid on November 24, 2010, 09:59:45
So far I needed to do this for my viewcomponents:::


-(void)onRegister {
LoginViewController *tVC = [self viewComponent];
tVC.delegate = self;

as I had some issues, but maybe after having fixed those, I can go back to the sample code.

Title: Re: Linking UI element and Mediator
Post by: bmonke on August 12, 2011, 10:38:50
you have to do several things to set it up.

1) In the view component's header file, you have to define the protocol with the methods that the mediator will implement.

2) You have to define the delegate in the header's interface like
id<NameOfDelegate> delegate then make it a property and synthesize it.

3) You then have to have an IBAction method in the view components implementation if you are relying on a touch gesture in a NIB file. it is here that you actually call the delegate like
[delegate nameOfMethodInProtocol] I have found that if you are sending the name of the button being touched or other data, it has to be sent as an argument along with this method.

4)In the mediator's header file, you must set the protocol on the mediator
Mediator <NameOfDelegate>
5)You just mentioned having to set the delegate in the onRegister method

6)You then finally have the method(s) from 1 above put into the mediators implementation file.

It is somewhat of a pain, obviously. But then again, you do almost the same amount of work in Flash with dispatching an event. Depending on your AS3 editor, it could actually be less typing with xcode's code completion.