通过一些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;
}
答案 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
}
希望这有帮助。