调用 setImage: 后 UIButton 不会更新它的图像

Posted

技术标签:

【中文标题】调用 setImage: 后 UIButton 不会更新它的图像【英文标题】:UIButton doesn't renew it's image after setImage: is called 【发布时间】:2012-07-24 21:26:10 【问题描述】:

问题来了——我有一个类,它是 UIView 的子类(一张卡片)。它在自身上创建一个按钮,并在用户触摸它时调用 changeStateIndicator:。

然后在按下按钮后卡片必须翻转并且按钮应该改变它的颜色(实际上是图像)。但它根本没有发生,所以翻转在按钮改变之前开始。这是我的代码:

//Adding a button to my view
UIButton *changeStateButton = [UIButton buttonWithType:UIButtonTypeCustom];
[changeStateButton setImage:[UIImage imageNamed:imageToInitWith] forState:UIControlStateNormal];
[changeStateButton setImage:[UIImage imageNamed:imageToInitWith] forState:UIControlStateHighlighted];
changeStateButton.frame = CGRectMake(0, 0, 30, 30);
changeStateButton.center = CGPointMake(self.bounds.size.width/2+([myWord length]*8)+17, 35);
changeStateButton.tag = 77;
[changeStateButton addTarget:self action:@selector(changeStateIndicator:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:changeStateButton];

//Method which is called when the button is touched
- (void)changeStateIndicator:(UIButton *)sender

    [sender setImage:[UIImage imageNamed:@"StateYellow"] forState:UIControlStateNormal];
    [sender setImage:[UIImage imageNamed:@"StateYellow"] forState:UIControlStateHighlighted];
    currentWord.done = [NSNumber numberWithInt:currentWord.done.intValue-10];
    [self prepareForTest];


//Method which flips the card
- (void)prepareForTest

    testSide = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"cal_small3"]];
    [UIView transitionFromView:self toView:testSide duration:0.5 options:UIViewAnimationOptionTransitionFlipFromRight completion:nil];

我的猜测是发件人在方法 -changeStateIndicator 结束之前不会更改其图像,但我不太确定这是实际问题。请帮帮我。

【问题讨论】:

您是否尝试过不调用方法 prepareForTest 来检查按钮是否按照您的预期改变颜色? 还有延迟动画怎么办 不用prepareForTest也能正常工作)我知道,因为我们在做同一个项目) 是的,不用调用 prepareForTest 一切正常。延迟实际上解决了问题。我仍然认为有更好的解决方案,但非常感谢,真的。 【参考方案1】:

试着推迟这个电话:

dispatch_async(dispatch_get_main_queue(), ^ [self prepareForTest]; );

如果这种方法有效,但仍然不是你想要的,那么使用 dispatch_after() 或

[self performSelector:@selector(prepareForTest) withObject:nil afterDelay:0.25f];

(如果需要,您可以使用时间为“0”的第二次调用而不是调度 - 同样的事情。)

【讨论】:

谁能告诉我为什么我们应该把它移到主线程?或者也许主要原因是让它异步? 问题是这样的:当那个动作消息被调用时,他的按钮仍然被关闭,所以你可以将任何长时间运行的任务推迟到该事件发生之后,让按钮刷新。由于 UIKit 就是这样工作的,因此该操作消息将进入主线程。现在,如果且仅当您知道可能访问的任何 IVAR 或属性实际上是线程安全的(设置/清除和使用)时,您可以将测试分派给任何线程 - 在 99% 的情况下,它不是线程安全的.除非你有一个非常好的理由来线程这个不。如果你这样做,你需要设计它是如何工作的。【参考方案2】:

当调用drawRect: 方法时,您需要在运行循环中再执行一次按钮重绘自身。 setImage: 方法只是设置它在这样做时将使用的图像。相反,您在此之前启动动画。这就是为什么一个非常短的延迟可以解决问题的原因。

解决此问题的另一种方法,甚至可能在美学上更具吸引力,是对按钮图像更改进行动画处理。当该动画完成后,启动另一个。

【讨论】:

以上是关于调用 setImage: 后 UIButton 不会更新它的图像的主要内容,如果未能解决你的问题,请参考以下文章

ios Custom UIButton scale setImage down不工作

UIButton setTitleColor 和 setImage 不起作用

UIButton setImage 不适用于自定义注释视图

使用 Swift 2.0 更新 UIButton 图像

在 UIButton 中,setImage 和 setBackgroudnImage 的内容 id 不同,它旋转了 90 度

iOS开发笔记10-关于UIButton的 setBackgroundImage 和 setImage区别