All UIElements become inaccessible after animation completes

此生再无相见时 提交于 2019-12-23 21:14:10

问题


I am trying to implement city lights animations by having an array of CGRect's with the coordinates of each light. Then creating UIViews around these CGRects. This logic (Thanks to Darren for helping with this logic) is working fine however after the animation is complete, all other elements (UIButtons, Sliders, Other UIImageViews etc) on screen become inaccessible. Even my Swipe gestures are not responding. Before and during the animation, all elements respond well BUT once the animation is complete, they all become inaccessible. I also tried [UIView bringSubviewToFront:] to bring some of the elements in front to see if that helps to make them accessible but it didn't help. I think that's not the issue because even if I try to create the lights view by sending them to background [self.view sendSubviewToBack:light]; everything becomes inaccessible after the animation is complete.

I would appreciate if someone can help/suggest me what am I missing.

Here is my code logic and corresponding scene for city lights animation. rects & lits are 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];
}

回答1:


It appears that once all lights are lit, the while loop runs continuously trying to get a random number that isn't lit. This is what will be blocking the main thread.

All you need is to check if all lights are lit at the beginning of the method and continue if not.

At the bottom of your lightRandomLight method, replace

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

with

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

and it'll stop when all the lights are lit.




回答2:


You are blocking the main thread - lightRandomLight calls itself when it is finished, with a 0.2 second delay. Therefore the main thread will never be responsive to user interaction. Look at the animation API provided by UIView - rather than "animating" by adding and removing subviews, you can set the alpha status or background colour of views, and you can set delays and set up loops.




回答3:


My guess is that while (!escape) {} will never complete (so escape is never YES).



来源:https://stackoverflow.com/questions/12478685/all-uielements-become-inaccessible-after-animation-completes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!