在 iPhone 7 上的动画块冻结 UI 中调用 layoutIfNeeded

Posted

技术标签:

【中文标题】在 iPhone 7 上的动画块冻结 UI 中调用 layoutIfNeeded【英文标题】:Calling layoutIfNeeded in animations block freezes UI on iPhone 7 【发布时间】:2017-08-31 08:09:37 【问题描述】:

有没有人遇到过同样的问题,在动画块中调用 layoutIfNeeded 会冻结 UI?

我有一个方法:

- (void)hide 
dispatch_block_t onMain = ^
    CGFloat height = -viewContent.frame.size.height;

    [UIView animateKeyframesWithDuration:0.15f delay:0 options:0 animations:^
        [UIView addKeyframeWithRelativeStartTime:0.f relativeDuration:0.7f animations:^
            self.constraintViewContentBottom.constant = height/3;
            [self layoutIfNeeded];
        ];
        [UIView addKeyframeWithRelativeStartTime:0.7f relativeDuration:0.3f animations:^
            self.constraintViewContentBottom.constant = height;
            [self layoutIfNeeded];
        ];
     completion:^(BOOL finished) 
        [UIView animateWithDuration:0.2f animations:^
            self.viewBackground.alpha = 0.0f;
        
                         completion:^(BOOL finished) 
                             self.hidden = YES;
                         ];
    ];
;
if([NSThread isMainThread]) 
    onMain();

else 
    dispatch_sync(dispatch_get_main_queue(), onMain);


这在许多设备上都能完美运行,但在一部 iPhone 7 上,这行:[self layoutIfNeeded]; 冻结 UI。

我无法调试该设备,但可以从中获取一些日志。

有谁知道我们如何解决这个问题?

感谢任何帮助。

【问题讨论】:

【参考方案1】:

在动画块之前设置约束的常量。 layoutIfNeeded 是唯一必须放入块中的东西...

【讨论】:

好吧,基本上如果我们从 [UIView animateWithDuration:0.2f animations:^] 调用它;方法 - 你是对的。但我尝试过不同的变体——之前,内部——结果是一样的。 =( 你必须使用dispatch_sync? 不要使用 dispatch_sync! 使用 dispatch_async 代替 好吧,伙计们,它从不调用 =) 默认情况下它从主线程调用:)

以上是关于在 iPhone 7 上的动画块冻结 UI 中调用 layoutIfNeeded的主要内容,如果未能解决你的问题,请参考以下文章

ios 应用程序滞后并在 iOS 13 中冻结 iphone 6s/7/8

UIView 动画冻结

使用动画推送视图控制器会冻结 UI

Android RecyclerView 在 notifyDataSetChanged 调用上冻结 UI

WCF:尽管调用是异步的,但 DNS 查找会冻结 UI

在单独的线程中调用 MFC UI 类上的方法