iosobjective-cdelegatestarget-action

Is it possible to use a delegate to send a message when the event is not produced by a UIButton?


I'd like to know how to use a delegate to send a clock message to MyViewController from a class called MotionListener but am having trouble translating Apple's explanation of target-action into a workable command.

Target-action is a design pattern in which an object holds the information necessary to send a message to another object when an event occurs. The stored information consists of two items of data: an action selector, which identifies the method to be invoked, and a target, which is the object to receive the message.]1

I have no trouble applying the explanation (above) in the example (below) with myButton using a delegate to send a message to a target called fromButtonInSubview whenever it is pressed

        [mySyncButton addTarget:self.delegate
                         action:@selector(fromSyncButtonInSubview:)
               forControlEvents:UIControlEventTouchUpInside];

I would assume that in order to send a signal that does not originate from a UIButton, I would still need to declare the protocol [a], give it a property [c] and include an initialisation method [b]

[a]

    @protocol SyncDelegate <NSObject>

    -(void)fromSync:(int)clock;

    @end

    @interface MotionListener : NSObject {

    }

[b]

    - (id) initMotionSensingWith:(float)updateInterval;

[c]

    @property (assign) id<SyncDelegate> delegate;

    @end

and declare the protocol in the interface [d] and add the target method in the implementation [e]

[d]

    @interface PlayViewController : UIViewController <SyncDelegate>

[e]

    - (void)fromSync:(int)clock
    {
        NSLog(@"tick"); // do stuff and show
    }

then in MyViewController, import MotionListener[f], declare it in the implementation [g] and define the delegate [h]

[f]

    #import "MotionListener.h"

[g]

    MotionListener *sync = [[MotionListener alloc] initMotionSensingWith:(float)updateInterval];

[h]

    sync.delegate = self;

But despite re-reading the explanation quoted above and after several failed attempts, I have yet to write a command that will send a sync signal from MotionListener to MyViewController. I know it will have the effect of addTarget:self.delegate and action:@selector(fromSync:) in the UIButton example (above). And before anyone suggests NSTimer selector, I already clock this at 50 Hz whereas the sync signal is 1 Hz

e.g.

     [NSTimer scheduledTimerWithTimeInterval:0.02;  // 50 Hz
                                      target:self
                                    selector:@selector(motionRefresh:)
                                    userInfo:nil
                                     repeats:YES];

    - (void)motionRefresh:(id)sender
    {
        count = (count + 1) % 50;  // every 1 second

        if (count == 0 ) 
        {
            // send the sync message here
            // EDIT
            NSLog(@"sending %i", count);
            [self.delegate fromSync:(int)count];
        }
    }

So my question is: using a delegate how can I send a sync message each time count turns 0 ? The answer is probably embarrassingly simple but I can wear that if you can help. Thanks.


Solution

  • I'm not sure if I understand your code correctly. but I think you simply have to replace your // send the sync message here line with a call to your delegate like [self.delegate fromSync:WHATEVERVALUEYOUWANTTOINFORMABOUT];.