簡體   English   中英

如何傾聽UIButton狀態的變化?

[英]How listen for UIButton state change?

我正在擴展具有通用功能的UIButton ,以根據顯示的標題更改某些外觀屬性。

為此,我需要檢測並響應“state”屬性的變化。 這樣,如果用戶為不同的狀態設置了不同的標題,我確保正確調整外觀。 我以為我需要使用某種KVO,如下所示:

[self addObserver:self 
       forKeyPath:@"state" 
          options:NSKeyValueObservingOptionNew 
          context:nil];

但這似乎沒有觸發@“state”或@“currentTitle”的observeValueForKeyPath:...方法。 我假設這是因為UIButton沒有為這些屬性實現KVO模式。

我不想只聽點擊。 這些事件導致狀態改變,但不是唯一的潛在原因。

有沒有人知道如何傾聽和回應UIButton的狀態變化?

謝謝


UPDATE

因為我在過去幾年中學到了一些東西,所以只是一個注釋;)。

我已經和一些知道的蘋果人談過了,而且KVO沒有在國家財產上工作的原因是因為UIKit的NONE肯定是符合KVO的。 在這里值得重復的思考 - 如果你試圖聽取UIKit框架類的任何屬性,請注意它可能有效,但是沒有得到官方支持,可能會在不同的iOS版本上中斷。

好吧,我找到了一個有效的解決方案。 您可以收聽按鈕titleLabel的text屬性。

[self.titleLabel addObserver:self 
                  forKeyPath:@"text" 
                     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 
                     context:nil];

它似乎每次更改都會被觸發兩次,因此您應該檢查以確保傳遞的更改字典中的@“old”和@“new”的值不同。

注意:不要直接使用@“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

MyButton.m

#import "MyButton.h"

#pragma mark - Private interface
@interface MyButton ()
- (void)checkStateChangedAndSendActions;
@end

#pragma mark - Main class
@implementation MyButton
{
    // Prior state is used to compare the state before
    // and after calls that are likely to change the
    // state. It is an ivar rather than a local in each
    // method so that if one of the methods calls another,
    // the state-changed actions only get called once.
    UIControlState  _priorState;
}

- (void)setEnabled:(BOOL)enabled
{
    _priorState = self.state;
    [super setEnabled:enabled];
    [self checkStateChangedAndSendActions];
}

- (void)setSelected:(BOOL)selected
{
    _priorState = self.state;
    [super setSelected:selected];
    [self checkStateChangedAndSendActions];
}

- (void)setHighlighted:(BOOL)highlighted
{
    _priorState = self.state;
    [super setHighlighted:highlighted];
    [self checkStateChangedAndSendActions];
}

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    _priorState = self.state;
    [super touchesBegan:touches withEvent:event];
    [self checkStateChangedAndSendActions];
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    _priorState = self.state;
    [super touchesMoved:touches withEvent:event];
    [self checkStateChangedAndSendActions];
}

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    _priorState = self.state;
    [super touchesEnded:touches withEvent:event];
    [self checkStateChangedAndSendActions];
}

- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
    _priorState = self.state;
    [super touchesCancelled:touches withEvent:event];
    [self checkStateChangedAndSendActions];
}

#pragma mark - Private interface implementation
- (void)checkStateChangedAndSendActions
{
    if(self.state != _priorState)
    {
        _priorState = self.state;
        [self sendActionsForControlEvents:UIControlEventStateChanged];
    }
}

@end

您可以使用UIButton init方法以編程方式創建它,或者通過向視圖添加普通UIButton並將類更改為MyButton ,從Interface Builder中使用它,但您必須以編程方式偵聽UIControlEventStateChanged事件。 例如,來自控制器類中的viewDidLoad ,如下所示:

[self.myButton addTarget:self 
                  action:@selector(myButtonStateChanged:) 
        forControlEvents:UIControlEventStateChanged];
[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];
}

子類UIButton,覆蓋setState:對我有用。 這可能不是最好的方法,但我已經成功完成了。

對於上述答案道歉,這是錯誤的。 本來應該看看我的代碼。 在我的情況下,我只需要根據高亮改變狀態,所以我覆蓋 - setHighlight:改變我需要的任何值。 因人而異。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM