0

我会尽可能清楚地解释我的问题。我有一架钢琴,你可以弹奏并录制你所做的歌曲,你弹奏的钢琴的每个按钮,这个按钮都会突出显示。问题是我有另一个按钮来播放我录制的歌曲,但我想要的是突出显示正在发声的钢琴的每个按钮。这是我编写的函数的一部分:

- (IBAction)play:(id)sender
{   
    for(NSString *string in [Singleton sharedInstance].notesMusicals)
        if([string isEqualToString:@"doMenor"]){
            UIImage *buttonImage = [UIImage imageNamed:@"do-menor_ON.png"];
            [doMenorButton setImage:buttonImage forState:UIControlStateNormal];
            CFBundleRef mainBundle = CFBundleGetMainBundle();
            CFURLRef soundFileURLRef;
            soundFileURLRef = CFBundleCopyResourceURL(mainBundle,(CFStringRef) @"Do_m", CFSTR ("mp3"), NULL);
            UInt32 soundID;
            AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
            AudioServicesPlaySystemSound(soundID);
            //doMenorButton.highlighted = YES;
             sleep(1);

        }
        else if([string isEqualToString:@"Re"]){
            UIImage *buttonImage = [UIImage imageNamed:@"do-menor_OFF.png"];
            [doMenorButton setImage:buttonImage forState:UIControlStateNormal];
            UIImage *buttonImage1 = [UIImage imageNamed:@"re_ON.png"];
            [reButton setImage:buttonImage1 forState:UIControlStateNormal];
            CFBundleRef mainBundle = CFBundleGetMainBundle();
            CFURLRef soundFileURLRef;
            soundFileURLRef = CFBundleCopyResourceURL(mainBundle,(CFStringRef) @"Re", CFSTR ("mp3"), NULL);
            UInt32 soundID;
            AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
            AudioServicesPlaySystemSound(soundID);
            sleep(1);

        }

您可以看到,在每个音符中,我都会突出显示该音符的按钮,但我遇到的问题是该按钮仅在功能结束后才突出显示,因此一旦旋律完成,我的所有音符都会突出显示。我希望有一个人可以帮助我。

4

4 回答 4

0

问题是sleep(1)通话。用户界面元素只会在play函数返回到主运行循环时更新。

使用这种同步方法进行计时是一个糟糕的设计。例如,您可以使用NSTimer异步等待一秒钟。但这需要对您的play方法进行重大重新设计。

于 2012-08-15T11:34:28.800 回答
0

您必须有某种计时器对象(请参阅 参考资料NSTimer)来与音乐同步,然后根据需要突出显示按钮(确保为此使用主线程)。

这样做不会影响当前按下的按钮。

于 2012-08-15T11:46:30.293 回答
0

试试这个(我没有尝试编译这么多错别字等):

// Assumes ARC. Note that since the block retains "self", you won't get dealloc'd
// until the queued block has run. If the user wants to stop the music set "cancel = YES"

@implementation MyClass
{
    NSArray *notes;
    NSUInteger theNote;
    BOOL cancel;
}

- (void)playOneSound
{
    if(cancel) return;

    if([string isEqualToString:@"doMenor"]){
        UIImage *buttonImage = [UIImage imageNamed:@"do-menor_ON.png"];
        [doMenorButton setImage:buttonImage forState:UIControlStateNormal];
        CFBundleRef mainBundle = CFBundleGetMainBundle();
        CFURLRef soundFileURLRef;
        soundFileURLRef = CFBundleCopyResourceURL(mainBundle,(CFStringRef) @"Do_m", CFSTR ("mp3"), NULL);
        UInt32 soundID;
        AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
        AudioServicesPlaySystemSound(soundID);
        //doMenorButton.highlighted = YES;
    }
    else if([string isEqualToString:@"Re"]){
        UIImage *buttonImage = [UIImage imageNamed:@"do-menor_OFF.png"];
        [doMenorButton setImage:buttonImage forState:UIControlStateNormal];
        UIImage *buttonImage1 = [UIImage imageNamed:@"re_ON.png"];
        [reButton setImage:buttonImage1 forState:UIControlStateNormal];
        CFBundleRef mainBundle = CFBundleGetMainBundle();
        CFURLRef soundFileURLRef;
        soundFileURLRef = CFBundleCopyResourceURL(mainBundle,(CFStringRef) @"Re", CFSTR ("mp3"), NULL);
        UInt32 soundID;
        AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
        AudioServicesPlaySystemSound(soundID);
    }
    // now going to queue up another sound to play in 1 second, leaving your UI responsive
    double delayInSeconds = 1.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^{ [self playOneSound];} );
}

- (IBAction)play:(id)sender
{
    notes = [Singleton sharedInstance].notesMusicals;
    theNote = 0;
    cancel = NO;
    // by defering til the next runLoop round, the play button gets to unhilite
    dispatch_async(dispatch_get_main_queue(), ^{ [self playOneSound];} );
}
于 2012-08-15T11:47:34.837 回答
-1

尝试在单独的线程中调用您的突出显示代码

[self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray];

例如:

...
        else if([string isEqualToString:@"Re"]){
            [self performSelectorInBackground:@selector(highlight:) withObject:myButton];
            CFBundleRef mainBundle = CFBundleGetMainBundle();
            CFURLRef soundFileURLRef;
            soundFileURLRef = CFBundleCopyResourceURL(mainBundle,(CFStringRef) @"Re", CFSTR ("mp3"), NULL);
            UInt32 soundID;
            AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
            AudioServicesPlaySystemSound(soundID);
            sleep(1);

        }

...

-(void) highlight:(UIButton)*button
{
                UIImage *buttonImage1 = [UIImage imageNamed:@"re_ON.png"];
                [button setImage:buttonImage1 forState:UIControlStateNormal];
}

如果代码中有任何错别字,请原谅。我在编辑器中对其进行了修改。

您需要修改我的示例以停用其他突出显示的按钮,但这应该没问题

于 2012-08-15T11:28:36.210 回答