Событие изменения UISegmentedControl не срабатывает в iOS5
У меня есть UISegmentedControl, чье событие "Изменено значение" подключено в Interface Builder для вызова моего контроллера -(IBAction)segmentChangeAction:(id)sender;
Когда пользователь нажимает на элемент управления для изменения выбранного сегмента, как ожидается, segmentChangeAction
вызывается в iOS4 или iOS5.
Когда я программно меняю выделенный сегмент на segmentedControl.selectedSegmentIndex = newIndex;
, на iOS4 segmentChangeAction
вызывается, и сегмент отражает новый выбор. Однако на iOS5 segmentChangeAction
не вызывается, но сегмент отражает новый выбор.
Является ли это изменением в iOS5? Есть ли что-нибудь, что я могу сделать, чтобы получить segmentChangeAction
, вызванный в iOS5, когда я программно меняю выбор?
Ответы
Ответ 1
Это изменение в 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
}
}
Ответ 2
Я нашел другой способ, возможно, немного легче понять
вы можете расширить 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
И вы можете установить делегат в вызывающем классе