确定currentPlaybackTime是否为cuepoint

时间:2014-01-04 18:13:35

标签: ios objective-c nstimer mpmovieplayer nstimeinterval

通过一些help from stackoverflow,我设法实现了一个计时器,每隔1/10秒检查一次媒体播放器视频中的currentPlaybackTime变量。

我还有NSArray个具有时间属性(NSNumber)的Cue对象。我想要一些代码,只是检查currentPlaybackTime是否匹配cue数组中的一个时间属性并返回cue对象。

到目前为止我的进展:

- (void) PollPlayerTimer_tick:(NSObject *)sender {
    if (self.movieController.playbackState == MPMoviePlaybackStatePlaying)
        self.lastRecordedPlaybackTime = self.movieController.currentPlaybackTime;

        if (decidingStatement) {
        // Do something
        }
}

decidingStatement必须是:

[NSNumber numberWithDouble:self.movieController.currentPlaybackTime] doubleValue]等于提示中的时间属性之一。它似乎不能使用[NSNumber numberWithDouble:self.movieController.currentPlaybackTime] doubleValue] == 3.9(例如),因为currentPlaybackTime可能是3.99585,而不是3.9。如果我检查currentPlaybackTime是否在3.9的正负0.1秒内,它就可以工作。

第二个问题是我必须搜索cues数组以获得提示时间。我可以迭代数组来获取时间属性。但是,每秒十次迭代一个数组似乎不是最好的做法。

必须有更好的方法!

更新

danh下面有一个很好的解决方案,代码目前看起来像:

- (void) PollPlayerTimer_tick:(NSObject *)sender {

    if (self.movieController.playbackState == MPMoviePlaybackStatePlaying)
        self.lastRecordedPlaybackTime = self.movieController.currentPlaybackTime;
    NSInteger *decidingStatement = [self indexOfCueMatching:[[NSNumber numberWithDouble:self.movieController.currentPlaybackTime] doubleValue] in:self.video.cues];
        if (decidingStatement) {

        }

}

- (NSComparisonResult)number:(NSNumber *)nA nearlyEquals:(NSNumber *)nB within:(double)epsilon {

    double dNa = [nA doubleValue];
    double dNb = [nB doubleValue];

    if (fabs(dNa - dNb) < epsilon) return NSOrderedSame;
    if (dNa < dNb) return NSOrderedAscending;
    return NSOrderedDescending;
}

- (NSInteger)indexOfCueMatching:(NSNumber *)playbackTime in:(NSArray *)cues {

    NSInteger index = self.lastCheckedIndex+1;
    if (index >= cues.count) return NSNotFound;

    NSComparisonResult compResult = [self number:[cues[index] time] nearlyEquals:playbackTime within:0.1];
    while (index<cues.count && compResult == NSOrderedAscending) {
        compResult = [self number:[cues[++index] time] nearlyEquals:playbackTime within:0.1];
    }
    self.lastCheckedIndex = index;

    return (compResult == NSOrderedSame)? index : NSNotFound;
}

1 个答案:

答案 0 :(得分:1)

问题一是在一定容差范围内匹配NSNumber双打。这看起来像这样:

- (NSComparisonResult)number:(NSNumber *)nA nearlyEquals:(NSNumber *)nB within:(double)epsilon {

    double diff = [nA doubleValue] - [nB doubleValue];

    if (fabs(diff) < epsilon) return NSOrderedSame;
    else return (diff < 0.0)? NSOrderedAscending : NSOrderedDescending;
}

问题二是更算法。从玩家那里获得任意时间的数字数组中的提示肯定是一个搜索,但它是一个带有一些非常大的提示的搜索:a)提示可能被排序,b)播放时间顺序出现,单调增加。

保持一个小状态,就像你检查的最后一个地方的索引一样,你应该做很少或不需要迭代你的数组。

@property (assign, nonatomic) NSInteger lastCheckedIndex;

在某处,在您开始之前,请指定self.lastCheckedIndex = -1。然后,每次计时器触发时,获取当前播放时间,将其换行为[NSNumber numberWithDouble:,然后调用以下内容:

- (NSInteger)indexOfCueMatching:(NSNumber *)playbackTime in:(NSArray *)cues {

    NSInteger index = self.lastCheckedIndex+1;
    if (index >= cues.count) return NSNotFound;

    NSComparisonResult compResult = [self number:cues[index] nearlyEquals:playbackTime within:0.1];
    while (index<cues.count && compResult == NSOrderedAscending) {
        compResult = [self number:cues[++index] nearlyEquals:playbackTime within:0.1];
    }
    self.lastCheckedIndex = index;

    return (compResult == NSOrderedSame)? index : NSNotFound;
}

这应该回答你的cue数组中匹配的索引,或者如果找不到匹配的cue则回答NSNotFound。此外,这应该更新lastCheckedIndex,知道下次来自播放器的时间将大于最后一次,并且下一次在你的cue数组中也会更大。

编辑 - 具体来说,就像这样使用它......

NSTimeInterval playbackTime = self.movieController.currentPlaybackTime;
self.lastRecordedPlaybackTime = playbackTime;

NSNumber *playbackTimeNumber = [NSNumber numberWithDouble:playbackTime];
NSInteger index = [self indexOfCueMatching:playbackTimeNumber in:self.video.cues];

if (index != NSNotFound) {
    // whatever we do when we find a matching cue
}

希望这有帮助。