2014-09-23 8 views
2

我是IOS/Objective C的新手,想要找出创建集合,迭代它和时间事件的最佳方法。遍历IOS中的NSDictionary和计时事件

我有一系列的歌曲,我希望歌曲的某一行出现在屏幕上,因为音乐在歌曲的正确位置播放。所以我开始做以下事情:我把个别行放入字典中,并在行显示时显示毫秒值。

NSDictionary *bualadhBos = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithInt:2875], @"Muid uilig ag bualadh bos, ", 
          [NSNumber numberWithInt:3407], @"Muid uilig ag tógáil cos, ", 
          [NSNumber numberWithInt:3889], @"Muid ag déanamh fead ghlaice, ", 
          [NSNumber numberWithInt:4401], @"Muid uilig ag geaibíneacht. ", 
          [NSNumber numberWithInt:4900], @"Buail do ghlúine 1, 2, 3, ", 
          [NSNumber numberWithInt:5383], @"Buail do bholg mór buí, ", 
          [NSNumber numberWithInt:5910], @"Léim suas, ansin suigh síos, ", 
          [NSNumber numberWithInt:6435], @"Seasaigh suas go hard arís. ", 
          [NSNumber numberWithInt:6942], @"Sín amach do dhá lamh, ", 
          [NSNumber numberWithInt:7430], @"Anois lig ort go bhfuil tú ' snámh. ", 
          [NSNumber numberWithInt:7934], @"Amharc ar dheis, ansin ar chlé, ", 
          [NSNumber numberWithInt:8436], @"Tóg do shúile go dtí an spéir. ", 
          [NSNumber numberWithInt:8940], @"Tiontaigh thart is thart arís, ", 
          [NSNumber numberWithInt:9436], @"Cuir síos do dhá lámh le do thaobh, ", 
          [NSNumber numberWithInt:9942], @"Lámha suas is lúb do ghlúin, ", 
          [NSNumber numberWithInt:10456], @"Suigí síos anois go ciúin. ", nil 
          ]; 

那么我想遍历字典,创建一个定时器,将调用负责在textLayer

for (id key in bualadhBos) { 
    NSTimer *timer; 
    timer = [[NSTimer scheduledTimerWithTimeInterval:bualadhBos[key] target:self selector:@selector(changeText) userInfo:nil repeats:NO]]; 

} 

-(void)changeText { 
    // change the text of the textLayer 
    textLayer.string = @"Some New Text"; 
} 

但是作为改变文本的方法,我开始调试这和检查它是如何工作的,我在调试器中注意到这些项目出现在词典中的顺序已经全部被打乱了。我还担心(我对此不太了解),我正在创建多个定时器,并且可能会有更高效的方法来解决此问题。

任何方向将不胜感激。

+0

参见http://stackoverflow.com/questions/376090/nsdictionary-with-ordered-keys – 2014-09-23 13:50:01

+0

字典是无序的。把你的项目放在一个数组中(你可能需要定义一个“容器”对象),按开始时间排序,然后遍历数组。 – 2014-09-23 15:19:58

回答

2

字典按照最合适的哈希算法的排序按定义排序,因此您应永远不要依靠它们的顺序。

在你的情况下,最好是建立一个二叉树并且有一个NSTimer每秒触发一次,执行二叉树搜索并返回提供时间偏移的最接近的字符串。

如果使用AVFoundation或AVPlayer进行播放。然后为了使字幕与媒体播放同步,您可以使用类似addPeriodicTimeObserverForInterval之类的东西来每秒触发一次定时器,并在您的二叉树中执行搜索并更新UI。

在伪码:

[player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) { 
    // get playback time 
    NSTimeInterval seconds = CMTimeGetSeconds(time); 

    // search b-tree 
    NSString* subtitle = MyBtreeFindSubtitleForTimeInterval(seconds); 

    // update UI 
    myTextLabel.text = subtitle; 
}]; 
+0

谢谢,我会看看这个。 – 2014-09-23 14:46:03

2

我注意到在调试器中,项目出现在词典中的顺序已经全部洗牌了。

词典不是有序集合。不要依赖于元素的顺序与添加元素的顺序相同。在任何方面都不要依赖元素的顺序。

如果要以特定顺序访问字典的元素,请按照您偏好的顺序创建包含键的数组。然后迭代数组并使用每个键访问数组中的对应值。在你的情况下,你可以得到键的数组,按升序排序,并使用它。或者,您可以创建一个包含“time”和“lyric”键的字典数组,每行一个。

说了这么多,就目前的代码而言,很难看出为什么你需要按特定顺序访问元素。如果你一次创建所有的定时器,就像你现在正在做的那样,事情应该正常工作,直到定时器的数量成为问题。我不知道在这一点上是,但我敢肯定它比20

我创建多个计时器更大,并有可能是一个更有效的方法来解决这个问题

当然。您正在为每条线同时创建一个计时器,以便许多计时器同时运行。您可以改为创建第一个计时器,并在其触发时创建另一个计时器,以此类推每行。为避免计时器漂移,使用系统时间计算适当的延迟时间,以显示下一行的时间。

+1

谢谢 - 你帮助我更清楚地认识到这个问题。是的,这是关于顺序的一个好的观点,不管是计时器在何时发生,但是我没有提到的,我想要做的是能够暂停和重新启动。如果有多个计时器,那将是一场噩梦。所以我认为你使用数组的建议是正确的选择。谢谢您的帮助。 – 2014-09-23 14:13:57