Firemarble Firemarble - 1 year ago 101
Objective-C Question

NSTimer is not firing from Singlton Class

I have a singleton class that I want to run in the background and check for photos to upload. The singleton is initialized from another viewcontroller via

[[EXOImageUploader sharedPhotoUploader] startPhotoUploadCheck];

If I NSLog everyting, it appears the singleton is working. I can do other things in the singleton that aren't shown below just fine. The
just never fires. I have even commented out the line that checks to see if the timer
but that doesn't work either.

Any idea on why my Timer is working?

Here is the order that the NSLog's spit out.

  1. sharedPhotoUploader init

  2. doSetup

  3. Timer interval: 1.000000

  4. sharedPhotoUploader singleton

  5. startPhotoUploadCheck

Here is the code.


@interface EXOImageUploader : NSObject
@property (assign) NSTimeInterval timerCheckInterval;

+ (EXOImageUploader *) sharedPhotoUploader;

- (void) startPhotoUploadCheck;
- (void) stopPhotoUploadCheck;


@interface EXOImageUploader ()

@property (nonatomic, strong) NSTimer* timerUpload;

@implementation EXOImageUploader

static EXOImageUploader* _sharedPhotoUploader;

#pragma mark - SINGLETON SETUP

+ (EXOImageUploader *) sharedPhotoUploader {

static EXOImageUploader *sharedPhotoUploader = nil;
static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
sharedPhotoUploader = [[self alloc] init];
NSLog(@"sharedPhotoUploader singleton");
return sharedPhotoUploader;


- (id) init {
if (self = [super init]){
NSLog(@"sharedPhotoUploader init");
[self doSetup];

return self;

- (void) doSetup {
if (!self.timerCheckInterval) {
self.timerCheckInterval = 1.0f;
NSLog(@"Timer interval: %f", self.timerCheckInterval);


#pragma mark Public Methods

- (void) startPhotoUploadCheck {
//Don't start a new one if this one is running
if (!_timerUpload) {
_timerUpload = [NSTimer timerWithTimeInterval:_timerCheckInterval target:self selector:@selector(checkForPhotosToUpload) userInfo:nil repeats:YES];


- (void) stopPhotoUploadCheck {
[_timerUpload invalidate];
_timerUpload = nil;

Answer Source

Use scheduledTimerWithTimeInterval instead of timerWithTimeInterval.

The docs for timerWithTimeInterval say: "You must add the new timer to a run loop, using addTimer:forMode:".

With the "scheduled" version, that's already done for you.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download