【问题标题】:All UIElements become inaccessible after animation completes动画完成后所有 UIElement 都无法访问
【发布时间】:2023-03-31 17:53:02
【问题描述】:

我正在尝试通过一个 CGRect 数组和每个灯光的坐标来实现城市灯光动画。然后围绕这些 CGRects 创建 UIViews。这个逻辑(感谢Darren 帮助解决这个逻辑)工作正常,但是在动画完成后,屏幕上的所有其他元素(UIButtons、Sliders、其他 UIImageViews 等)都变得无法访问。甚至我的滑动手势也没有响应。在动画之前和期间,所有元素都响应良好,但是一旦动画完成,它们都变得不可访问。我还尝试[UIView bringSubviewToFront:] 将一些元素放在前面,看看这是否有助于使它们易于访问,但没有帮助。我认为这不是问题,因为即使我尝试通过将它们发送到背景[self.view sendSubviewToBack:light]; 来创建灯光视图,动画完成后一切都变得无法访问。

如果有人可以帮助/建议我缺少什么,我将不胜感激。

这是我的城市灯光动画的代码逻辑和相应的场景。 rects 和 lits 是 ivars。

- (void)viewDidLoad {
    pageCount=5;
    AVAudioSession * audioSession = [AVAudioSession sharedInstance];
    //Setup the audio session
    //...
    pageNum=1;
    //put imageviews in place
    //...
    //load a page
    [self loadPage];
    [self loadAudio];

    [self cityLightsSetUp];
    [super viewDidLoad];
}


-(void)loadPage{
    //Logic to load page...    
    /...
    if (pageNum == 3){
      [self startCityLights];
    }
}


- (void)cityLightsSetUp
{
    rects = [[NSMutableArray alloc] init];
    lit = [[NSMutableArray alloc] init];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(58, 217, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(71, 217, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(84, 217, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(97, 217, 10, 10)]];

    [rects addObject:[NSValue valueWithCGRect:CGRectMake(58, 231, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(71, 231, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(84, 231, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(97, 231, 10, 10)]];

    [rects addObject:[NSValue valueWithCGRect:CGRectMake(58, 245, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(71, 245, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(84, 245, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(97, 245, 10, 10)]];

    [rects addObject:[NSValue valueWithCGRect:CGRectMake(58, 258, 10, 10)]];
    [rects addObject:[NSValue valueWithCGRect:CGRectMake(71, 258, 10, 10)]];
}

- (void)startCityLights
{
    [self lightRandomLight];
    [self performSelector:@selector(switchOffRandomLight) withObject:nil afterDelay:1.0];
}

- (void)lightRandomLight
{
    BOOL escape = NO;
    int rand;

    while (!escape) {
        BOOL alreadyLit = NO;
        rand = arc4random() % [rects count];
        // Check if already lit
        for (UIView *view in lit) {
            CGRect litRect = view.frame;
            CGRect ranRect = [[rects objectAtIndex:rand] CGRectValue];
            if (CGRectContainsRect(litRect, ranRect)) {
                alreadyLit = YES;
            }
        }

        if (!alreadyLit) {
            UIView *light = [[UIView alloc] initWithFrame:[[rects objectAtIndex:rand] CGRectValue]];
            light.backgroundColor = [UIColor orangeColor];
            [lit addObject:light];
            [self.view addSubview:light];
            //[self.view sendSubviewToBack:light];
            escape = YES;
        }
    }

    [self performSelector:@selector(lightRandomLight) withObject:nil afterDelay:0.2];
}

- (void)switchOffRandomLight
{
     NSLog(@"switchOffRandomLight");
    int rand = arc4random() % [lit count];
    UIView *light = [lit objectAtIndex:rand];
    [lit removeObject:light];
    [light removeFromSuperview];

    [self performSelector:@selector(switchOffRandomLight) withObject:nil afterDelay:0.5];
}

【问题讨论】:

    标签: ios objective-c uielement


    【解决方案1】:

    似乎一旦所有的灯都亮了,while 循环就会连续运行,试图获得一个未亮的随机数。这就是阻塞主线程的原因。

    你只需要在方法开始时检查所有灯是否都点亮,如果没有则继续。

    在你的 lightRandomLight 方法的底部,替换

    [self performSelector:@selector(lightRandomLight) withObject:nil afterDelay:0.2];
    

    与

    if ([lit count] != [rects count]) {
        [self performSelector:@selector(lightRandomLight) withObject:nil afterDelay:0.2];
    } else {
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
    }
    

    当所有的灯都亮起时它会停止。

    【讨论】:

    • 谢谢达伦。我会试试这个并告诉你。
    【解决方案2】:

    您正在阻塞主线程 - lightRandomLight 在完成时调用自身,延迟 0.2 秒。因此主线程永远不会响应用户交互。看看 UIView 提供的动画 API——不是通过添加和删除子视图来“动画化”,而是可以设置视图的 alpha 状态或背景颜色,还可以设置延迟和设置循环。

    【讨论】:

    • 感谢 jrturton,为我解释了这个问题。正如您所指出的,可能是它阻塞了主线程。你能请。向我解释有关此解决方案/方法中要进行的更正的更多信息?我将不胜感激...
    • 这与其说是更正,不如说是对代码的完全重写。看看我提到的动画方法 ([UIView animate...]),看看它们如何适用于您的情况。
    • 我不认为这是一个主线程问题,因为你说你在灯光亮起时一切都会响应。只有在你有问题的时候。
    • 抱歉,直到所有灯都亮起,主线程才被阻塞。看我的回答。这是 while 循环阻止它,而不是每 0.2 秒重复调用一次
    【解决方案3】:

    我的猜测是 while (!escape) {} 永远不会完成(所以逃生永远不会是)。

    【讨论】:

      猜你喜欢
      • 2012-03-06
      • 2013-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      相关资源
      最近更新 更多