Objective c 目标C在程序结束前不触发计时器

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

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

AppDelegate.h 歌手
@protocol-SongPlayerDelegate;
@接口歌曲播放器:NSObject{
id uu不安全u未获得授权的代表;
}
@属性(非原子,赋值)id委托;
-(id)playMyQueue:NSMutableArray;
@结束
@协议SongPlayerDelegate
-(void)歌曲演奏者:(歌曲演奏者*)演奏者做了某事:(id)enity;
-(无效)歌曲播放器:(歌曲播放器*)播放器更新滑翔器:(双)结果;
@结束
-(id)playMyQueue:(id)实体{
…
NSDictionary*dict=[(DesktopSoundEntity*)实体标记字典];
NSString*dur=[dict objectForKey:kTagDuration];
_songDurration=[dur doubleValue];
_然后=[NSDate date];
如果(_myTimer){
[_mytimerinvalidate];
_myTimer=nil;
}
_myTimer=[NSTimer scheduledTimerWithTimeInterval:0.75目标:自我
选择器:@selector(updatetime:)userInfo:nil repeats:YES];
[自我播放歌曲];
[self passBackURL:entity];
返回零;
}
-(void)UpdateTime:(NSTimer*)计时器{
double now=([\u then timeIntervalSinceNow]*-1);
NSLog(@“现在->%f”,现在);
双秒=(现在/_songduration)*100;
NSLog(@“现在->%f”,秒);
如果(秒>100){
[_mytimerinvalidate];
_myTimer=nil;
}
NSLog(@“滑块应更新”);
[self.delegate songPlayer:self updateSlider:sec];
}

滑块在playMyQueue方法完成之前不会更新,我看到了条跳转,并得到了NSLog消息。如果您有任何建议,我们将不胜感激。

计时器不会启动,除非它们被安排在具有运行循环的线程中
performSelectorInBackground:…
不保证工作将安排在具有runloop的线程中,并且在任何情况下,只要调用的选择器退出,线程就可以重新获得


要修复此问题,请将计时器移动到具有运行循环的线程。考虑到您正在破坏w/UI位,主线程可能是最佳选择。

请1)发布您的真实代码(
返回nil;
不编译)-2)花时间格式化/缩进代码以使其更具可读性。感谢Martin,应该返回nil;我是这方面的新手,将尝试修复更改滑块值后是否有[slider display|显示?playSong有什么作用?在播放过程中,它肯定会出现阻止主线程(或以不同的运行循环模式运行)的情况。DigiMonk,我会尝试一下,但我从未访问过NSLog(“slider应该正在升级”)在从PlaySong方法发送值之前的语句(参见上文)。但是,当歌曲结束时,消息和滑块开始工作。谢谢,您已经给了我要查看的区域。我是Objective C的新手,不太确定需要将循环插入何处,以便在滑块上平滑滑动。我认为该值最好在SongPlayer方法中导出,并将该值传递给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];
}