Событие изменения UISegmentedControl не запускается в iOS5 - PullRequest
36 голосов
/ 08 ноября 2011

У меня есть UISegmentedControl, чье событие «Значение изменено» подключено в Интерфейсном Разработчике для вызова -(IBAction)segmentChangeAction:(id)sender;

моего контроллера

Когда пользователь нажимает на элемент управления, чтобы изменить выбранный сегмент, как и ожидалось, вызывается segmentChangeAction в iOS4 или iOS5.

Когда я программно изменяю выбранный сегмент с помощью segmentedControl.selectedSegmentIndex = newIndex;, на iOS4 вызывается segmentChangeAction, и сегмент отражает новый выбор. Однако на iOS5 segmentChangeAction вызывается , а не , но сегмент отражает новый выбор.

Это изменение в iOS5? Можно ли что-нибудь сделать, чтобы вызвать segmentChangeAction на iOS5, когда я программно изменил выбор?

Ответы [ 2 ]

70 голосов
/ 08 ноября 2011

Это изменение в iOS 5 для того, чтобы UISegmentedControl соответствовал всем другим элементам управления.

Идея состоит в том, что действие должно запускаться автоматически только в результате взаимодействия с пользователем. До iOS 5 действия UISegmentedControl выполнялись из-за взаимодействия с пользователем и программного взаимодействия. Однако инициирование изменения программно означает, что вы также можете сделать [myControl sendActionsForControlEvents:UIControlEventValueChanged] самостоятельно.

Однако вы должны быть осторожны с этим. Скажем, вы делаете:

[segmentedControl setSelectedSegmentIndex:newIndex];
[segmentedControl sendActionsForControlEvents:UIControlEventValueChanged];

Если вы соберете и запустите это на iOS 5, все будет работать так, как вы ожидаете. Если вы создадите и запустите это на iOS 4, ваши действия будут запущены дважды (один раз, когда вы setSelectedSegmentIndex, и снова, когда вы sendActions...).

Способ обойти это - сделать какую-то охрану. Это может быть проверка во время выполнения, чтобы показать, что вы работаете на устройстве с iOS 5+, или даже что-то более приземленное, например:

// changingIndex is a BOOL ivar
changingIndex = YES;
[segmentedControl setSelectedSegmentIndex:newIndex];
changingIndex = NO;
[segmentedControl sendActionsForControlEvents:UIControlEventValueChanged];

и затем в вашем методе действия ...

- (void)segmentedControlSelectedIndexChanged:(id)sender {
  if (!changingIndex) {
    // your action code here, guaranteed to only run as a result of the sendActions... msg
  }
}
5 голосов
/ 16 октября 2012

Я нашел другой способ, возможно, немного легче понять, что вы можете расширить UISegmentedControl и добавить целевое действие в методы init и вызвать метод делегата для запуска изменения значения

, вот пример кода

заголовочный файл выглядит следующим образом

#import <UIKit/UIKit.h>
@class CGUISegmentedControl;

@protocol CGUISegmentedControlDelegate <NSObject>

@optional
- (void) segmentedControl:(CGUISegmentedControl *) control valueChangedTo:(NSInteger) nValue;

@end

@interface CGUISegmentedControl : UISegmentedControl

@property (nonatomic,unsafe_unretained) id <CGUISegmentedControlDelegate> delegate;

@end

.m file

    #import "CGUISegmentedControl.h"

@implementation CGUISegmentedControl

@synthesize delegate                = _delegateAction;

- (void) addTargetAction {

    [self addTarget:self action:@selector(indexChanged:) forControlEvents:UIControlEventValueChanged];

}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addTargetAction];
    }
    return self;
}

- (id) initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder:aDecoder];
    if (self) {
        [self addTargetAction];
    }
    return self;

}

- (id) initWithItems:(NSArray *)items {

    self = [super initWithItems:items];
   if (self) {
        [self addTargetAction];
    }
    return self;
}

- (id) init {

    self = [super init];
    if (self) {
        [self addTargetAction];
    }
    return self;

}

- (void) indexChanged:(id) sender {

    if (_delegateAction && [_delegateAction respondsToSelector:@selector(segmentedControl:valueChangedTo:)])
        [_delegateAction segmentedControl:self valueChangedTo:self.selectedSegmentIndex];


}

@end

И вы можете установить делегата в вызывающем классе

...