在AppDelegate中,我有一个NSMutableArray,其中包含一组在后台方法(正在播放的歌曲)中处理的类。应用程序的那部分工作正常。我设置了委托方法,并在数组的每个项目结束时接收工作状态。我想添加一个NSSlider来显示正在处理的每个数组项的状态。我在AppDelegate中测试了单个实体上的滑块,并得到了我期望的结果。问题是当我正在处理队列时,NSTimer在工作单元完成之前不会被触发,就像延迟了一样。我怀疑我没有正确安排它(因为计时器使用AppDelegate中的相同代码处理单首歌曲)。
@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource,
NSTableViewDelegate, NSSharingServiceDelegate,
NSSharingServicePickerDelegate, SongPlayerDelegate>
-(void) songPlayer:(SongPlayer *)player didSomething:(DesktopEntity *)entity;
-(void) songPlayer:(SongPlayer *)player updateSlider:(double)result;
-(void)previewQueue:(DesktopEntity *)entity {
…
// schedule work
_queuePlayer = [[SongPlayer alloc] init];
_queuePlayer.delegate = self;
[_queuePlayer performSelectorInBackground:@selector(playMyQueue:) withObject:_queue];
}
@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消息。任何建议将不胜感激。
答案 0 :(得分:2)
除非在具有正在运行的运行循环的线程中调度计时器,否则它们不会触发。 performSelectorInBackground:..
没有保证工作将在带有runloop的线程中进行调度,并且在任何情况下,只要调用的选择器退出,就可以获得线程。
要修复,请将该计时器移动到具有正在运行的运行循环的线程。主线程可能是最好的选择,因为你正在使用UI位。