Search code examples
iosobjective-csingletonnstimer

NSTimer is not firing from Singleton 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 everything, it appears the singleton is working. I can do other things in the singleton that aren't shown below just fine. The NSTimer just never fires. I have even commented out the line that checks to see if the timer isValid 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.

.h

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

+ (EXOImageUploader *) sharedPhotoUploader;

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

.m

@interface EXOImageUploader ()

@property (nonatomic, strong) NSTimer* timerUpload;
@end

@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 {
     NSLog(@"doSetup");
    if (!self.timerCheckInterval) {
        self.timerCheckInterval = 1.0f;
    }
    NSLog(@"Timer interval: %f", self.timerCheckInterval);

}

#pragma mark Public Methods

- (void) startPhotoUploadCheck {
    NSLog(@"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 {
     NSLog(@"stopPhotoUploadCheck");
    [_timerUpload invalidate];
    _timerUpload = nil;
}

Solution

  • 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.