Lisa
Lisa

Reputation: 3526

Objective C repeated callback required

I'm quite new to iOS development, and I've been trying to solve the following problem:

I have a ViewController displaying information that changes with time. I have another controller (TimeController) managing time. TimeController has an NSTimer firing every second to check whether I've entered a new time slot (there's some logic behind it, and if I've entered a new time slot that means that the information in the ViewController needs to be updated.

In my understanding, I need some kind of callback procedure but I couldn't figure out how to do it - I read about blocks but to be honest they're quite overwhelming and I couldn't relate my problem to the examples I saw.

The TimeController looks something like the following:

// TimeController.h

@interface TimeController : NSObject

@property (weak) NSTimer *periodicTimer;
@property NSInteger timeslot;

@end

// TimeController.m
#import "TimeController.h"

@implementation TimeController

-(void)startTimer {
    self.periodicTimer = [NSTimer scheduledTimerWithTimeInterval:(1) target:self 
             selector:@selector(onTimer) userInfo:nil repeats:YES];
}

-(void)onTimer {
    // check if anything has changed.
    // If so, change timeslot. Notify "listening" objects.
}

In a simple example with a single ViewController depending on TimeController, I'm imagining something like this:

// ViewController.h
@interface ViewController : UIViewController

@property TimeController* timeCtrl;

@end

// ViewController.m
#import "ViewController.h"
#import "TimeController.h"

-(void)onNotificationFromTimeController {
    // timeslot has changed in the TimeController.
    NSInteger tslot = timeCtrl.timeslot;

    // figure out new display value depending on tslot. Update the view
}

What's missing here (among other stuff like proper initialisation of timeCtrl) are the callback mechanisms. I'd appreciate any help on this!

Upvotes: 0

Views: 247

Answers (1)

Mattias
Mattias

Reputation: 2306

Notifications

Add a listener to the event (let's call it "TimeNotificationEvent") in ViewController:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onNotificationFromTimeController) name:@"TimeNotificationEvent" object:nil];

In the onTimer method in TimeController.m, add the following code to post a notification:

[[NSNotificationCenter defaultCenter] postNotificationName:@"TimeNotificationEvent" object:nil];

Sidenote: To stop listening for notifications:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"TimeNotificationEvent" object:nil];
  • Easy to setup
  • You can have multiple listeners for the same event

Blocks

Add a property in TimeController.h:

@property (nonatomic, copy) dispatch_block_t timerBlock;

Add a call to the timerBlock in TimeController.m:

-(void)onTimer {
    // Check for nil to avoid crash
    if (_timerBlock) {
        _timerBlock();
    }
}

Assign the block in ViewController:

_timeCtrl.timerBlock = ^{
    // Do stuff to the UI here
};
  • A bit more complex (retain cycles, syntax etc)
  • Only one listener (with this particular example implementation)
  • Easier to follow the code

Upvotes: 2

Related Questions