ios7.1 で修正されました
修正のための微調整は行わないでください。
どうやら同じ問題がiOS 8.0および8.1で再び発生する
ios9.2 で修正されました
修正のための微調整は行わないでください。
こんにちは今日はUISwitch's
イベントValueChanged:
で見ました-continuously
を呼び出しながらOn
をOff
またはOff
に変更し、指を動かしましたまだ右側と左側にあります。 NSLogでGIF画像をより鮮明にするように工夫しました。
私の値の変更方法は次のとおりです。
- (IBAction)changeSwitch:(id)sender{
if([sender isOn]){
NSLog(@"Switch is ON");
} else{
NSLog(@"Switch is OFF");
}
}
iOS6のスイッチと同じコードが期待どおりに動作します:
だから、その状態をオンまたはオフに一度だけ呼び出すことを誰も私に提案できます。またはこれはバグですか?
UPDATE
ここにそれの私のデモがあります:
私は同じ問題に直面している多くのユーザーを得たので、これはUISwitch
のバグかもしれないので、それを一時的に解決するために今見つけました。 gitHub
custom KLSwitch
を1つ見つけましたAppleがxCodeの次のアップデートでこれを修正することを願っています。
次のコードをご覧ください。
-(void)viewDidLoad
{
[super viewDidLoad];
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(130, 235, 0, 0)];
[mySwitch addTarget:self action:@selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:mySwitch];
}
- (void)changeSwitch:(id)sender{
if([sender isOn]){
NSLog(@"Switch is ON");
} else{
NSLog(@"Switch is OFF");
}
}
ここに同じバグ。簡単な回避策を見つけたと思います。 BOOL
の以前の状態を保存する新しいUISwitch
と、IBAction
(Value Changed fired)のifステートメントを使用して、スイッチの値が実際に持っていることを確認するだけです。かわった。
previousValue = FALSE;
[...]
-(IBAction)mySwitchIBAction {
if(mySwitch.on == previousValue)
return;
// resetting the new switch value to the flag
previousValue = mySwitch.on;
}
これ以上奇妙な動作はありません。それが役に立てば幸い。
UISwitch
の.selected
プロパティを使用して、値が実際に変更されたときにコードが1回だけ実行されるようにすることができます。サブクラス化や新しいプロパティの追加が不要になるため、これは素晴らしいソリューションだと思います。
//Add action for `ValueChanged`
[toggleSwitch addTarget:self action:@selector(switchTwisted:) forControlEvents:UIControlEventValueChanged];
//Handle action
- (void)switchTwisted:(UISwitch *)twistedSwitch
{
if ([twistedSwitch isOn] && (![twistedSwitch isSelected]))
{
[twistedSwitch setSelected:YES];
//Write code for SwitchON Action
}
else if ((![twistedSwitch isOn]) && [twistedSwitch isSelected])
{
[twistedSwitch setSelected:NO];
//Write code for SwitchOFF Action
}
}
そして、これはSwiftにあります:
func doToggle(switch: UISwitch) {
if switch.on && !switch.selected {
switch.selected = true
// SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
} else {
switch.selected = false
}
}
アプリで非常に多くのスイッチを使用している場合、UISwitchのアクションメソッドが定義されているすべての場所でコードを変更するのに問題があります。カスタムスイッチを作成し、値が変更された場合にのみイベントを処理できます。
CustomSwitch.h
#import <UIKit/UIKit.h>
@interface Care4TodayCustomSwitch : UISwitch
@end
CustomSwitch.m
@interface CustomSwitch(){
BOOL previousValue;
}
@end
@implementation CustomSwitch
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
previousValue = self.isOn;
}
return self;
}
-(void)awakeFromNib{
[super awakeFromNib];
previousValue = self.isOn;
self.exclusiveTouch = YES;
}
- (void)setOn:(BOOL)on animated:(BOOL)animated{
[super setOn:on animated:animated];
previousValue = on;
}
-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
if(previousValue != self.isOn){
for (id targetForEvent in [self allTargets]) {
for (id actionForEvent in [self actionsForTarget:targetForEvent forControlEvent:UIControlEventValueChanged]) {
[super sendAction:NSSelectorFromString(actionForEvent) to:targetForEvent forEvent:event];
}
}
previousValue = self.isOn;
}
}
@end
値が変更された値と同じ場合、イベントを無視します。ストーリーボードのUISwitchのすべてのクラスにCustomSwitchを配置します。これにより、問題が解決し、値が変更されたときにターゲットを1回だけ呼び出します。
スイッチの値の変更に即座に対応する必要がない場合は、次の解決策が考えられます。
- (IBAction)switchChanged:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if ([switch isOn]) {
[self performSelector:@selector(enable) withObject:nil afterDelay:2];
} else {
[self performSelector:@selector(disable) withObject:nil afterDelay:2];
}
}
この問題は、iOS 9.3ベータ版の時点でまだここにあります。ユーザーがスイッチの外にドラッグできないことを気にしない場合、.TouchUpInside
ではなく.ValueChanged
を使用すると確実に機能することがわかります。
この問題は、スイッチを他の動作に結びつけるときに悩みます。通常、物事はon
からon
に移行することを好みません。これが私の簡単な解決策です。
@interface MyView : UIView
@parameter (assign) BOOL lastSwitchState;
@parameter (strong) IBOutlet UISwitch *mySwitch;
@end
@implementation MyView
// Standard stuff goes here
- (void)mySetupMethodThatsCalledWhenever
{
[self.mySwitch addTarget:self action:@selector(switchToggled:) forControlEvents:UIControlEventValueChanged];
}
- (void)switchToggled:(UISwitch *)someSwitch
{
BOOL newSwitchState = self.mySwitch.on;
if (newSwitchState == self.lastSwitchState)
{
return;
}
self.lastSwitchState = newSwitchState;
// Do your thing
}
self.lastSwitchState
を手動で変更するたびに、必ずmySwitch.on
も設定してください! :)
IOS 9.2でもまだ同じ問題に直面しています
私は解決策を得て、それが他の人を助けるかもしれないとポーズをとった
メソッドが呼び出された回数をトレースするカウント変数を作成する
int switchMethodCallCount = 0;
スイッチ値のブール値を保存
bool isSwitchOn = No;
Switchの値変更メソッドでは、最初のメソッド呼び出しに対してのみdesireアクションを実行します。スイッチ値が再び設定カウント値とt bool変数値をデフォルトに変更したとき
- (IBAction)frontCameraCaptureSwitchToggle:(id)sender {
//This method will be called multiple times if user drags on Switch,
//But desire action should be perform only on first call of this method
//1. 'switchMethodCallCount' variable is maintain to check number of calles to method,
//2. Action is peform for 'switchMethodCallCount = 1' i.e first call
//3. When switch value change to another state, 'switchMethodCallCount' is reset and desire action perform
switchMethodCallCount++ ;
//NSLog(@"Count --> %d", switchMethodCallCount);
if (switchMethodCallCount == 1) {
//NSLog(@"**************Perform Acction******************");
isSwitchOn = frontCameraCaptureSwitch.on
[self doStuff];
}
else
{
//NSLog(@"Do not perform");
if (frontCameraCaptureSwitch.on != isSwitchOn) {
switchMethodCallCount = 0;
isSwitchOn = frontCameraCaptureSwitch.on
//NSLog(@"Count again start");
//call value change method again
[self frontCameraCaptureSwitchToggle:frontCameraCaptureSwitch];
}
}
}
このタイプの問題は、多くの場合ValueChangedが原因です。機能を実行するためにボタンを押す必要はありません。タッチイベントではありません。プログラムでスイッチをオン/オフに変更するたびに、値が変更され、IBAction関数が再度呼び出されます。
@RoNiTには正しい答えがありました:
Swift
func doToggle(switch: UISwitch) {
if switch.on && !switch.selected {
switch.selected = true
// SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
} else {
switch.selected = false
}
}
これは私のために働いた。
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
self.switch.isOn = true
}
DispatchQueue.main.async {
self.mySwitch.setOn(false, animated: true)
}
これは正常に機能し、セレクター関数を再度呼び出しません。