Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

ArtOfWarfare

macrumors G3
Original poster
Nov 26, 2007
9,561
6,059
I have a class that interprets accelerometer data (which makes it the model, right?) and then passes some info to the controller, whom it shouldn't know anything about beyond that it's an NSObject.

For example, in this code, the accelerometer interpreter determines that the device was moved abruptly enough to send a message to the controller:
Code:
    if ((zData - lastStoredZData < -0.10) && ([controller respondsToSelector:@selector(pressUp)]))
    {
      [controller pressUp];  
    }
    lastStoredZData = zData;

The issue is, xCode is giving me a warning that "Method '-pressUp' not found".

But I've already made sure that the controller has such a method before I tell it to run it. The app runs fine, but I'd rather make sure xCode doesn't give me false warnings, so I want to make sure, am I using introspection properly? I figure that having the accelerometer interpreter import the controller is a poor programing choice, because then it becomes too tightly integrated into this program and can't be as easily integrated into another program in the future (or if I decided to make it possible to change within this program which controller the accelerometer interpreter sends its data to.)

Edit: I just changed [controller pressUp]; to [controller performSelector:mad:selector(pressUp)]; which removed the compiler warning... is this actually somehow better?
 

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
[obj msg] and [obj performSelector:mad:selector(msg)] are pretty much the same thing. The former is likely to execute faster than the later, but that wouldn't matter in this case. It also becomes more cumbersome to use the later with many arguments, and you loose the compiler type checking of those arguments.

In the ideals of MVC, a model object should never have a connection from model to controller, even if it's a typeless connection. Instead, if a change happens in a model object that the controllers might want to react to, the model object should either use Key-Value Observing or broadcast a notification using NSNotificationCenter. Any interested controllers would have set themselves up to be notified of the change or notification.

In your case, this is an classic case for notification. To implement this the code in the model would be:
Code:
if (zData - lastStoredZData < -0.10) {
  [[NSNotificationCenter defaultCenter]
      postNotification:@"AbruptMovement"];
}
lastStoredZData = zData;

In your controller, you setup to observe the notification like so:
Code:
[[NSNotificationCenter defaultCenter]
    addObserver:self
       selector:@selector(pressUp:)
           name:@"AbruptMovement"
         object:nil];
And then:
Code:
- (void)pressUp:(NSNotification *)aNotification
{
}
 

Sydde

macrumors 68030
Aug 17, 2009
2,552
7,050
IOKWARDI
There are several ways to achieve the modularity you desire. First, you could define a protocol that your motion controller's client must conform to. That way, you will have a standardized set of methods to plug subsequent clients inti without the motion controller having to know anything else about the client.

Alternately, you could have the client supply selectors to the controller (@properties) for it to call.

In the first case, everything is cleanly defined and each object knows what to expect in the message passing. In the second case, the client object has the option of specifically directing messages to certain methods, depending on current circumstances, by setting the selector properties.

Note that a selector is a numerical value type, so 0 can be tested for, in case the client wants no message to be sent.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.