【问题标题】:Highlight button before the function ends in iOS在iOS中功能结束之前突出显示按钮
【发布时间】:2012-08-11 15:26:10
【问题描述】:

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

- (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);

        }

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

【问题讨论】:

    标签: objective-c ios function button highlight


    【解决方案1】:

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

    // 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];} );
    }
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        问题在于sleep(1) 调用。用户界面元素只有在play 函数返回主运行循环时才会更新。

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

        【讨论】:

          【解决方案4】:

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

          [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];
          }
          

          如果代码中有任何拼写错误,请原谅。我在编辑器中修改了它。

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

          【讨论】:

          • UI 元素只能在主线程上更新,不能在后台线程上更新。所以这行不通。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-10
          • 2015-09-27
          • 2019-04-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多