iOS7 UISwitch Etkinlik Değerini Değiştirdi: Sürekli arama bu Hata mı yoksa ne ..?


93

Düzenle

Şimdi sabitlendi
Düzeltmek için herhangi bir ince ayar yapmayın.

Düzenle2

Görünüşe göre aynı sorun iOS 8.0 ve 8.1'de tekrar oluyor

Düzenle3

Şimdi sabitlendi
Düzeltmek için herhangi bir ince ayar yapmayın.


Merhaba Bugün ben de görüldüğü UISwitch'sOlay ValueChanged:çağrılması continuously i değişikliği olduğum sürece Onhiç Offveya OffAçık olarak ve parmağım sol tarafında yanı sıra sağ tarafında hala taşındı. NSLog ile daha net olması için GIF görüntüsünü ekledim.

görüntü açıklamasını buraya girin

Değer Değiştirilen Yöntemim:

- (IBAction)changeSwitch:(id)sender{

    if([sender isOn]){
        NSLog(@"Switch is ON");
    } else{
        NSLog(@"Switch is OFF");
    }
    
}

iOS6, beklediğimiz gibi İyi çalışan Switch kodunun aynısı:

görüntü açıklamasını buraya girin

Bu yüzden birisi bana durumunu yalnızca bir kez Açık veya kapalı olarak aramamı önerebilir. veya bu bir hata mı yoksa ne ..?

GÜNCELLEME

İşte benim Demom:

programlı UISwitch Ekle

XIB'den UISwitch ekleyerek


1
Hala simülatörde iOS7.1'de bu hatayı alıyorum, henüz cihazı denemedim, xcode 5.1.1 çalıştırıyor
Fonix

3
7.1.2 ipad ile aynı sorunu yaşıyorum
Hassy

7
İOS 8.0 ve 8.1'de UISwitch ile aynı / benzer bir sorunu görebiliyorum
Sea Coast of Tibet

2
Hala 9.1'de. Lütfen openradar.appspot.com/15555929 herkesin bir kopyasını gönderin . Bunu düzeltmenin tek yolu bu.
Guillaume Algis

1
Görünüşe göre 9.3'te geri döndü
Ben Leggiero

Yanıtlar:


44

Lütfen aşağıdaki koda bakın:

-(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");
    }
}

Her iki şekilde de denediğimi ve aynı sonucu aldığımı söylediğim gibi cevap için teşekkürler. atlist swtich programatik ve xib sir'den nasıl ekleneceğini biliyorum.
Nitin Gohel

12

Aynı hata burada. Sanırım basit bir çözüm buldum. Anahtarın değerinin gerçekten değişip değişmediğini kontrol etmek için (Değer Değiştirildi) bölümümüzde BOOLönceki durumunu UISwitchve if ifadesini saklayan yeni bir tane kullanmalıyız IBAction.

previousValue = FALSE;

[...]

-(IBAction)mySwitchIBAction {
    if(mySwitch.on == previousValue)
        return;
    // resetting the new switch value to the flag
    previousValue = mySwitch.on;
 }

Artık tuhaf davranışlar yok. Umarım yardımcı olur.


2
bu sadece if (mySwitch.on == previousValue)
Keegan Jay

12

Kodunuzun yalnızca gerçek değer değiştiğinde bir kez yürütülmesini sağlamak için UISwitch's .selectedözelliğini kullanabilirsiniz. Bunun harika bir çözüm olduğunu düşünüyorum çünkü alt sınıflara girmek veya yeni özellikler eklemek zorunda kalmıyor.

 //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
    }
}

Ve işte Swift'de:

func doToggle(switch: UISwitch) {
    if switch.on && !switch.selected {
        switch.selected = true
        // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
    } else {
        switch.selected = false
    }
}

6
Bunu en basit buluyorum.
zekel

Bunu + 1'ledi çünkü geçiş mantığını yok saymak istediğimde .tag değerini doldurmak için benzer bir çözüm kullanmaya yönlendirdi. Bazen hem açık hem de kapalı modda ateşleme mantığına ihtiyacım var, böylece yukarıdakiler yeterli değildi.
davidethell

9

Uygulamanızda çok fazla anahtar kullanıyorsanız, UISwitch'in eylem yönteminin tanımlandığı tüm yerlerde kodu değiştirme sorunu vardır. Özel anahtar yapabilir ve olayları yalnızca değer değişirse işleyebilirsiniz.

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

Değer değiştirilen değerle aynıysa olayları yok sayıyoruz. Storyboard'daki tüm UISwitch sınıfına CustomSwitch'i koyun.Bu, sorunu çözecek ve değer değiştiğinde hedefi yalnızca bir kez çağıracaktır.


Bu benim için çalıştı. Yeniden kullanılabilir olduğundan ve uygulamasını sınıf uygulaması içinde gizlediğinden, uygulama dosyalarınıza gereksiz kodun manuel olarak eklenmesine neden olmaması açısından idealdir. Bu sadece iyi bir tasarım. Yine de bu cevabın daha fazla yorumu olsa güzel olurdu, çünkü kodun tamamının neden orada olduğunu gerçekten anlamıyorum.
James C

Teşekkürler, benim için çalıştı. Kodu biraz daha açıklar mısınız? @codester
Swayambhu

7

Aynı sorunla karşılaşan birçok kullanıcım var, bu yüzden bu hata olabilir, bu UISwitchyüzden şimdi geçici çözümü için buldum. Şimdilik bir gitHubözel KLSwitchkullanım buldum, Apple'ın bunu bir sonraki xCode güncellemesinde düzelteceğini umuyorum:

https://github.com/KieranLafferty/KLSwitch


6

Anahtarın değer değişikliğine anında tepki vermeniz gerekmiyorsa, aşağıdakiler bir çözüm olabilir:

- (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];
  }
}

İOS 11.2'de bir cazibe gibi çalıştı. Benim durumumda, arka arkaya 2 olay tetikledi (durum: kapalı, kaydırma: kapalı, 1. olay: açık, 2. olay: kapalı), bu nedenle 0.1 saniyelik bir gecikme benim için yeterli ve bir kullanıcı tarafından fark edilmiyor.
Paul Semionov

3

Bu sorun hala iOS 9.3 beta sürümünden itibaren burada. Kullanıcının anahtarın dışına sürükleyememesinin bir sakıncası yoksa, güvenilir bir şekilde çalışmak .TouchUpInsideyerine kullanmanın .ValueChangedişe yaradığını görüyorum .


2

Hala iOS 9.2'de aynı sorunla karşılaşıyorum

Bir çözüm buldum ve başkalarına yardımcı olabilirmiş gibi poz verdim

  1. Yöntemin kaç kez çağrıldığını izlemek için count değişkeni oluşturun

    int switchMethodCallCount = 0;
    
  2. Anahtar değeri için bool değerini kaydedin

    bool isSwitchOn = No;
    
  3. Switch'in değer değiştirme yönteminde, yalnızca ilk yöntem çağrısı için arzu eylemi gerçekleştirin. Anahtar değeri tekrar ayarlanan sayma değerini ve t bool değişken değerini varsayılana değiştirdiğinde

    - (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];
    
    
        }
    }
    
    
    }
    

Ben de 9.2'de hala bu sorunla karşı karşıyayım. Mantığınızı uyguladım ve şimdi istediğim gibi çalışıyor.
Nick Kohrn

2

Anahtarı diğer davranışlara bağladığımda bu sorun beni rahatsız ediyor. Genellikle işler bir noktadan ondiğerine gitmeyi sevmez on. İşte benim basit çözümüm:

@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.lastSwitchStateManuel olarak her değiştirdiğinizde de ayarladığınızdan emin olun mySwitch.on! :)


1

Bu tür bir soruna genellikle ValueChanged neden olur. Fonksiyonun çalışması için düğmeye basmanıza gerek yoktur. Dokunma olayı değil. Açma / kapama anahtarını programlı olarak her değiştirdiğinizde, değer değişir ve IBAction işlevini yeniden çağırır.

@RoNiT doğru cevabı verdi:

Swift

func doToggle(switch: UISwitch) {
    if switch.on && !switch.selected {
        switch.selected = true
        // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
    } else {
        switch.selected = false
    }
}

0
DispatchQueue.main.async {
        self.mySwitch.setOn(false, animated: true)
    }

Bu iyi çalışıyor ve seçici işlevini tekrar çağırmıyor.


0

Bu benim için çalıştı.

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
    self.switch.isOn = true
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.