Coldsteel48
Coldsteel48

Reputation: 3512

Multiple NSTimers issue

I have sub-classed a component (it looks like circle and there is a picture inside it (NSView subclass)).

I want to change the picture every X time (to make it look like an animation).

When in my main view controller I drawing 1 sub-class like this everything works Fine, but when I adding more the picture changes much faster with each.

(I am firing the picture change using an NSTimer) I am assuming that the issue happens because I have multiple NSTimers on the same queue

However I tried to use

NSTimer *uiTimer = [NSTimer timerWithTimeInterval:(1.0 / 5.0) target:self selector:@selector(changePicture) userInfo:nil repeats:YES];      
[[NSRunLoop mainRunLoop] addTimer:uiTimer forMode:NSRunLoopCommonModes];

It didn't solve the issue (I assume because it is still on the main thread) So I came up with NSThread Solution

[NSThread detachNewThreadSelector:@selector(updateModel) toTarget:self withObject:nil];


- (void) updateModel
  {

  [NSTimer scheduledTimerWithTimeInterval:secondsBetweenUpdates 
                                    target:self 
                                    selector:@selector(changePicture) 
                                    userInfo:nil 
                                    repeats:YES];
    [[NSRunLoop currentRunLoop] run];
    }

It has a bit different behaviour (but still no luck as more sub-classes I have as faster picture changes).

My last shoot was this solution:

// Update the UI 5 times per second on the main queue
// Keep a strong reference to _timer in ARC
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,     dispatch_get_main_queue());
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, (1.0 / 5.0) * NSEC_PER_SEC, 0.25 * NSEC_PER_SEC);

dispatch_source_set_event_handler(_timer, ^{
[self changePicture];
});

// Start the timer
dispatch_resume(_timer);

I am not usually giving up , but I am trying to resolve it for 3 days already... And I think I need and advice of how to do this so it will work as intended.

Upvotes: 0

Views: 97

Answers (1)

lucianomarisi
lucianomarisi

Reputation: 1552

If you are using GCD I would recommend you use dispatch_after, for example:

float delayTime = 0.2f;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                             (int64_t)(delayTime * NSEC_PER_SEC)),
               dispatch_get_main_queue(), ^{
    [self changePicture];
});

Upvotes: 1

Related Questions