目标C NSTimer在程序结束前不会触发

时间:2013-12-05 19:46:48

标签: objective-c cocoa nstimer scheduling

在AppDelegate中,我有一个NSMutableArray,其中包含一组在后台方法(正在播放的歌曲)中处理的类。应用程序的那部分工作正常。我设置了委托方法,并在数组的每个项目结束时接收工作状态。我想添加一个NSSlider来显示正在处理的每个数组项的状态。我在AppDelegate中测试了单个实体上的滑块,并得到了我期望的结果。问题是当我正在处理队列时,NSTimer在工作单元完成之前不会被触发,就像延迟了一样。我怀疑我没有正确安排它(因为计时器使用AppDelegate中的相同代码处理单首歌曲)。

AppDelegate.h

@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource,
    NSTableViewDelegate, NSSharingServiceDelegate,
    NSSharingServicePickerDelegate, SongPlayerDelegate>

-(void) songPlayer:(SongPlayer *)player didSomething:(DesktopEntity *)entity;
-(void) songPlayer:(SongPlayer *)player updateSlider:(double)result;

ApplDelegate.m

-(void)previewQueue:(DesktopEntity *)entity {
    …
// schedule work
    _queuePlayer = [[SongPlayer alloc] init];
    _queuePlayer.delegate = self;
    [_queuePlayer performSelectorInBackground:@selector(playMyQueue:) withObject:_queue];
}

SongPlayer.h

@protocol SongPlayerDelegate;
@interface SongPlayer : NSObject {
id<SongPlayerDelegate> __unsafe_unretained delegate;
}
@property (nonatomic, assign) id<SongPlayerDelegate> delegate;
-(id)playMyQueue:NSMutableArray;
@end

@protocol SongPlayerDelegate <NSObject>
- (void)songPlayer:(SongPlayer *)player didSomething:(id)enity;
- (void)songPlayer:(SongPlayer *)player updateSlider:(double)result;
@end
-(id) playMyQueue:(id)entity {
…

    NSDictionary *dict = [(DesktopSoundEntity *)entity tagDictionary];
    NSString *dur = [dict objectForKey:kTagDuration];
    _songDurration = [dur doubleValue];
    _then = [NSDate date];
    if (_myTimer) {
        [_myTimer invalidate];
        _myTimer = nil;
    }
    _myTimer = [NSTimer scheduledTimerWithTimeInterval:0.75 target:self
            selector:@selector(updateTimer:) userInfo:nil repeats:YES];

    [self playSong];
    [self passBackURL:entity];
    return nil;
}
- (void)updateTimer:(NSTimer *)timer {
    double now = ([_then timeIntervalSinceNow]*-1);
    NSLog(@"now-> %f", now);
    double sec = (now / _songDurration) *100;
    NSLog(@"now-> %f", sec);
    if (sec > 100) {
        [_myTimer invalidate];
        _myTimer = nil;
    }
    NSLog(@"SLIDER SHOULD BE UPDATING");
    [self.delegate songPlayer:self updateSlider:sec];
}

在playMyQueue方法完成之前,滑块不会更新,我看到栏跳转,我收到NSLog消息。任何建议将不胜感激。

1 个答案:

答案 0 :(得分:2)

除非在具有正在运行的运行循环的线程中调度计时器,否则它们不会触发。 performSelectorInBackground:..没有保证工作将在带有runloop的线程中进行调度,并且在任何情况下,只要调用的选择器退出,就可以获得线程。

要修复,请将该计时器移动到具有正在运行的运行循环的线程。主线程可能是最好的选择,因为你正在使用UI位。