隐藏属性无法在动画块中更改

Ale*_*lex 18 uiviewanimation ios swift

我在UIStackView中嵌入了两个UILabel.顶部标签始终可见,但底部标签通过hidden属性打开和关闭.我想要将此效果设置为动画,因此我将其粘贴在动画块中:

private func toggleResultLabel(value:Double) {
    if value == 0 {
        UIView.animateWithDuration(0.25) { () -> Void in
            self.resultLabel.hidden = true
        }
    } else {
        UIView.animateWithDuration(0.25) { () -> Void in
            // Something weird is happening. I had to add 3 of the same statements to get 
            // the hidden flag to be false
            self.resultLabel.hidden = false
            self.resultLabel.hidden = false
            self.resultLabel.hidden = false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是隐藏属性不会改变,除非我反复重复该语句(在这种情况下为3次).我在进入动画关闭时发现了这一点,并发现该属性不会改变它的赋值.现在我注意到看似随机发生的同样问题.true如果相关,则第二个标签的默认值为.

我在这里缺少什么,或者这是一个错误?

更新:为了它的价值,我通过添加removeArrangedSubview()以及addArrangedSubview():

if value == 0 {
    UIView.animateWithDuration(0.25) { () -> Void in
        self.resultLabel.hidden = true
        self.heroStackView.removeArrangedSubview(self.resultLabel)
    }
 } else {
    UIView.animateWithDuration(0.25) { () -> Void in
        self.heroStackView.addArrangedSubview(self.resultLabel)
        self.resultLabel.hidden = false
    }
 }
Run Code Online (Sandbox Code Playgroud)

Nik*_*kin 32

在iOS 11和之前,隐藏一个当arrangedSubview一个的UIStackView使用的UIView动画API多次,隐藏的属性值"栈",和它需要设置隐藏到false多次的值实际上改变之前.

在工作中,我们决定使用UIView扩展和一个解决方法,该方法仅为给定值设置隐藏一次.

extension UIView {

    // Workaround for the UIStackView bug where setting hidden to true with animation
    // mulptiple times requires setting hidden to false multiple times to show the view.
    public func workaround_nonRepeatingSetHidden(hidden: Bool) {
        if self.hidden != hidden {
            self.hidden = hidden
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这肯定是UIKit中的一个错误,请查看清楚再现它的示例项目.

在此输入图像描述

  • 2017年7月,bug还在,刚刚复现。感谢您的详尽回答。 (2认同)
  • iOS 14.2 中仍然存在问题。所提出的解决方案奏效了。 (2认同)

小智 7

隐藏标志设置为相同状态的次数以及在实际更改之前必须设置为不同状态的次数似乎存在关联.在我的情况下,我已经将隐藏标志设置为YES,然后在动画块中再次设置为YES,这导致了我必须在我的其他动画块中调用hidden = NO两次以使其再次可见的问题.如果我在第一个动画块中为同一个视图添加了更多的hidden = YES行,那么我必须在第二个动画块中有更多的hidden = NO行.这可能是UIStackView对隐藏标志的KVO观察中的错误,该隐藏标志在更改导致此问题的某个内部状态之前不会检查该值是否实际更改.

要暂时解决问题(直到Apple修复它),我为UIView和swizzled setHidden:方法创建了一个类别,该类别首先检查原始值并仅在与原始值不同时设置新值.这似乎没有任何不良影响.

@implementation UIView (MethodSwizzling)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(setHidden:);
        SEL swizzledSelector = @selector(UIStackViewFix_setHidden:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

- (void)UIStackViewFix_setHidden:(BOOL)hidden
{
    if (hidden != self.hidden) {
        [self UIStackViewFix_setHidden:hidden];
    }
}

@end
Run Code Online (Sandbox Code Playgroud)


kwa*_*ahn 6

似乎是UIStackView的Apple bug.请参阅以下内容......

UIStackView:用动画隐藏的切换卡在隐藏模式中http://www.openradar.me/22819594

我的解决方案虽然不是很理想,但却是在没有动画的情况下隐藏UIStackView.


CHi*_*-NY 5

在考虑UIStackView错误时,我决定检查隐藏属性.

if myView.hidden != hidden {
   myView.hidden = hidden
}
Run Code Online (Sandbox Code Playgroud)

这不是最优雅的解决方案,但它适用于我.