【问题标题】:Calling a method either the second time a condition occurs OR after a timeout, whichever comes first第二次发生条件或超时后调用方法,以先到者为准
【发布时间】:2011-03-23 06:04:14
【问题描述】:

在过去几天大量编码之后,我终于(嗯)卡住了。

我的应用程序侦听 iTunes 发送的外部 NSNotification。每当当前播放状态发生变化时都会发出通知,在这种情况下最有趣的是当前流标题发生变化时。当您连接到一个新的广播电台时,通常会发送 两个 通知 - iTunes 连接后立即发送一个,以电台名称作为标题,然后很快(一秒钟左右)发送一个实际的当前歌曲的艺术家和标题。我只对艺术家/标题组合或 second 通知感兴趣。 或者,如果在暂停两秒后仍然只发送一个通知,请使用第一个。 (由于无法预先知道会是一两个,所以我能想到的唯一方法就是超时。)

简而言之,我只想在条件发生第二次时调用方法,或者如果只发送一个通知,则在两秒超时后调用。两秒钟后它应该重新设置以再次执行整个交易。

有什么想法吗?

【问题讨论】:

    标签: objective-c cocoa timer notifications


    【解决方案1】:

    这并不太复杂。您只需要等待第一个通知,直到计时器触发或第二个通知到来。我在代码中输入的 cmets 应该会解释该过程。

    - (void)awakeFromNib {
        // Register for the notification you're interested in
        [[NSDistributedNotificationCenter defaultCenter] addObserver:self 
                                                            selector:@selector(iTunesNoteCallback:) 
                                                                name:NSTheiTunesNotificationImInterestedIn 
                                                              object:nil]; // @"iTunes"?
    }
    

    - (void)iTunesNoteCallback:(NSNotification *)note {
        // Check whether there's been a notification already
        if( !gotFirstNote ){
            // If so, hang on to it,
            gotFirstNote = YES;
            self.currNote = note; // With currNote declared as a retained property
            // and start a timer.
            noteTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 
                                                         target:self 
                                                       selector:@selector(actOniTunesInfo:) 
                                                       userInfo:nil repeats:NO];
        }
        else {
            // However, if we got a notification already,
            // hang on to the new one,
            self.currNote = note;
            // stop the timer, 
            [noteTimer invalidate];
            // and call the same method the timer would have
            [self actOniTunesInfo:nil];
        }
    }
    

    - (void)actOniTunesInfo:(NSTimer *)timer {
        // Reset the flag
        gotFirstNote = NO;
        // Use currNote; doesn't matter which one it is,
        // it's the best info we've gotten
    }
    

    如果通知有两种类型,那就更简单了。您不再需要标志,只需注册两个回调,一旦调用第二个,您就可以使计时器无效,释放第一个通知,并使用您刚刚获得的信息。

    【讨论】:

    • 谢谢。由于相对简单,我几乎采用了这个解决方案。 (由于线程,定时器有点棘手。)
    【解决方案2】:

    您需要创建一个数据模型来存储和建模通知以及它们的顺序和时间。

    首先,您需要一个数据对象来存储每个通知和有关通知的数据。 - 通知对象 - 通知到达的时间戳 - 通知类型

    然后你需要一个容器对象,它可以将数据对象保存在一个数组中,以及启动和捕获计时器。因此,当通知到达时,它会被分类,存储在数据对象中,然后将其推送到数组中。如果它是第一种类型的通知,则容器对象将启动一个两秒计时器。如果第二个类型的另一个通知到达,容器对象将终止计时器,但如果计时器触发,则它返回超过两秒的最后一个第一个类型通知的数据对象。

    触发操作后,清空容器对象并重新开始。

    【讨论】:

    • 这在我看来像是过度设计解决方案。可以直接保留通知对象;如果你已经有了,那就用新的吧。
    • 究竟什么对象会直接保留通知对象?你只是要把它塞进随机控制器的某个地方吗?您是否需要仅在应用程序中的位置访问通知,或者您可能需要多个访问点?在这种情况下,通知包含数据并结合它们的顺序和时间成为数据模型逻辑的一部分。根据我的经验,将此类数据封装在某种专用对象中可以节省时间。然后你就拥有了它,从那时起就不用担心了。您可以将数据对象插入到应用程序的任何位置,它会工作。
    猜你喜欢
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多