在iOS5中,UISegmentedControl的更改事件未触发

37

我有一个UISegmentedControl,它的“值改变”事件已在界面构建器中与我的控制器的-(IBAction)segmentChangeAction:(id)sender;连接。

当用户点击控件以更改选定段时,无论是在iOS4还是iOS5中,预期都会调用segmentChangeAction

当我通过segmentedControl.selectedSegmentIndex = newIndex;编程方式更改所选段时,在iOS4上会调用segmentChangeAction,并且该段将反映新选择。但是在iOS5上,尽管该段确实反映了新选择,但segmentChangeAction未被调用。

这是iOS5中的更改吗?是否有任何方法可以在我通过编程方式更改选择时在iOS5上调用segmentChangeAction

2个回答

72

这是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
感谢您的深入解释!我已经做了最简单的事情(在更改索引后直接调用segmentChangeAction),并验证了在iOS<5上两次调用此代码没有问题。但是,我现在感觉更加愉快,因为我知道为什么要这样做,谢谢。 - Clafou
@Vin,今年我太忙了,无法抽出时间来担任版主所应该付出的关注。 - Dave DeLong
@Clafou 不客气!如果你发现有一个 UIControl 没有遵循这个行为,请提交一个 bug,它会被修复的。 :) - Dave DeLong
@Dave 谢谢...我会查看他们的提名。 - Vin
顺便说一下,有一种更简洁的方法来检测 iOS 版本:BOOL atLeastIOS5_0 = [[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0; - Jon
显示剩余4条评论

5
我发现另一种方法,可能更容易理解。你可以扩展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文件

    #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

你可以在调用类中设置委托


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接