web-dev-qa-db-ja.com

iOS5でUISegmentedControl変更イベントが発生しない

コントローラーの-(IBAction)segmentChangeAction:(id)sender;を呼び出すために、「値が変更されました」イベントがInterface Builderに接続されているUISegmentedControlがあります。

ユーザーがコントロールをタップして選択したセグメントを変更すると、iOS4でもiOS5でも、予想どおりsegmentChangeActionが呼び出されます。

選択したセグメントをsegmentedControl.selectedSegmentIndex = newIndex;を介してプログラムで変更すると、iOS4ではsegmentChangeActionが呼び出され、セグメントに新しい選択が反映されます。ただし、iOS5ではsegmentChangeActionnotと呼ばれますが、セグメントには新しい選択が反映されます。

これはiOS5での変更ですか?プログラムで選択を変更したときに、iOS5でsegmentChangeActionを呼び出すためにできることはありますか?

36
Clafou

これは、UISegmentedControlが他のすべてのコントロールと一致するようにするためのiOS 5での変更です。

アイデアは、ユーザーの操作の結果としてのみアクションが自動的に発生するということです。 iOS 5より前のバージョンでは、ユーザーの操作andプログラムによる操作が原因で、UISegmentedControlのアクションが実行されていました。ただし、プログラムで変更を開始するということは、[myControl sendActionsForControlEvents:UIControlEventValueChanged]自分。

ただし、これには注意が必要です。あなたが言うと:

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

これをiOS 5でビルドして実行すると、期待どおりに動作します。これをiOS 4でビルドして実行すると、アクションが発生しますtwice(一度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
  }
}
70
Dave DeLong

別の方法を見つけました、おそらく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

そして、あなたは呼び出しクラスにデリゲートを設定することができます

5