Iphone 如何侦听UIButton状态更改?

Iphone 如何侦听UIButton状态更改?,iphone,objective-c,cocoa-touch,uibutton,key-value-observing,Iphone,Objective C,Cocoa Touch,Uibutton,Key Value Observing,我正在使用通用功能扩展ui按钮,以根据显示的标题更改某些外观属性 为了做到这一点,我需要检测并响应“state”属性中的更改。因此,如果用户为不同的状态设置了不同的标题,我会确保外观得到适当调整。我假设我需要使用某种KVO,如下所示: [self addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil]; 但这似乎并没有

我正在使用通用功能扩展
ui按钮
,以根据显示的标题更改某些外观属性

为了做到这一点,我需要检测并响应“state”属性中的更改。因此,如果用户为不同的状态设置了不同的标题,我会确保外观得到适当调整。我假设我需要使用某种KVO,如下所示:

[self addObserver:self 
       forKeyPath:@"state" 
          options:NSKeyValueObservingOptionNew 
          context:nil];
但这似乎并没有激发observeValueForKeyPath:。。。“状态”或“当前标题”的方法。我假设这是因为UIButton没有为这些属性实现KVO模式

我不想只听点击。这些事件会导致状态变化,但不是唯一的潜在原因

是否有人知道如何监听和响应UIButton的状态变化

谢谢


更新 在过去几年里,我学到了一些东西,所以只需要一个便条;)


此后,我与一些了解KVO的苹果人进行了交谈,KVO不在国有资产上工作的原因是,UIKit的保证符合KVO。我认为这一点值得在这里重复——如果您试图监听UIKit框架类的任何属性,请注意它可能会工作,但不受官方支持,并且可能会在不同的iOS版本上中断。

子类UIButton,override setState:对我来说是有效的。这可能不是最好的方法,但我已经成功地做到了


为上述答案道歉,这是错误的。应该看看我的代码。在我的例子中,我只需要根据highlight更改状态,所以我重写了-
setHighlight:
来更改我需要的任何值。YMMV.

好吧,我想出了一个有效的解决方案。您可以收听按钮标题标签的文本属性

[self.titleLabel addObserver:self 
                  forKeyPath:@"text" 
                     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 
                     context:nil];
它似乎每次更改都会被解雇两次,因此您应该检查以确保传递的更改字典中的@“old”和@“new”的值不同


注意:不要直接使用@“旧”和@“新”。常量分别是NSKeyValueChangeOldKey和NSKeyValueChangeNewKey。

我今天需要它,所以我编写了这个类来完成这项工作:

MyButton.h

#import <UIKit/UIKit.h>

// UIControlEventStateChanged uses the first bit from the UIControlEventApplicationReserved group
#define UIControlEventStateChanged  (1 << 24)

@interface MyButton : UIButton
@end
您可以使用
UIButton
init
方法以编程方式创建它,或者通过在视图中添加普通
UIButton
并将类更改为
MyButton
从Interface Builder使用它,但您必须以编程方式侦听
UIControlEventStateChanged
事件。例如,在控制器类中的
viewDidLoad
,如下所示:

[self.myButton addTarget:self 
                  action:@selector(myButtonStateChanged:) 
        forControlEvents:UIControlEventStateChanged];
如果您在观察者“selected”属性中进行检查,则可以正常工作

-(void)observeValueForKeyPath:(NSString *)keyPath  
                     ofObject:(id)object 
                       change:(NSDictionary *)change 
                      context:(void *)context
{
    if ([keyPath isEqualToString:@"selected"])
    {
        [self.img setImage:self.selected ? self.activeImg : self.inactiveImg];
    }
    else
        [super observeValueForKeyPath:keyPath
                             ofObject:object
                               change:change
                              context:context];
}

刚试过这个,它不起作用。UIControl文档同意:“此属性为只读,没有相应的setter方法。”您不应覆盖不应覆盖的方法。如果不同状态的文本相同,该怎么办?即使此属性仍然被重新设置为相同的内容,我认为您也不能保证不同iOS版本之间的行为,因为在某些状态更改情况下,实现可能不会设置文本。我写了一节课,并在另一个答案中发布了它-希望这对某人有用:)@jhabbott-当然,但是你改变了我问的问题。我特别尝试根据标题文本更改外观。如果标题文本实际上没有更改,则不会产生任何影响。也就是说,是的,如果有人关心任何形式的国家变化,你的答案可能是正确的——只是对我的需要来说有点太重了。这让我困惑:(我可以在问题的标题中看到,
如何侦听UIButton状态更改?
但正确的答案是,
您可以侦听文本属性。
。好吧..酷!但在我的特殊情况下,不可能依赖正在更改的标题:(如果不能用KVO来听,那么我希望看到一个相应的答案,或者至少有一个吼叫会让人觉得更有意义。我想知道,既然UIKit不兼容KVO,这是不是appstore验证被拒绝的原因?@Maskime-我不希望他们会拒绝该应用,除非你同意r的使用导致应用程序中出现明显的错误。Ehm,正如我所知,您不能将KVO设置为
状态
,因为
状态
未更改,它只返回
UIControl
的私有变量。我喜欢该解决方案,但将自定义事件命名为
UIControlEventStateChanged
,就好像它是框架的一部分一样。这s更像是一种黑客行为。是的,它是一种黑客行为。有时你不得不做一些黑客行为来解决所提供框架中的缺陷。这让我很难过。如果有一种非黑客方式来实现这一点,请发布一个答案,我很有兴趣看到它:)
[self addObserver:self 
       forKeyPath:@"state" 
          options:NSKeyValueObservingOptionNew 
          context:nil];
-(void)observeValueForKeyPath:(NSString *)keyPath  
                     ofObject:(id)object 
                       change:(NSDictionary *)change 
                      context:(void *)context
{
    if ([keyPath isEqualToString:@"selected"])
    {
        [self.img setImage:self.selected ? self.activeImg : self.inactiveImg];
    }
    else
        [super observeValueForKeyPath:keyPath
                             ofObject:object
                               change:change
                              context:context];
}