iOS7 UISwitch ने अपने इवेंट को बदल दिया है: लगातार कॉल करना यह बग है या क्या ..?


93

संपादित करें

यह अब तय हो गया है
इसे ठीक करने के लिए कोई ट्विक न करें।

EDIT2

जाहिरा तौर पर यही समस्या आईओएस 8.0 और 8.1 में फिर से होती है

Edit3

यह अब तय हो गया है
इसे ठीक करने के लिए कोई ट्विक न करें।


हाय मैं आज में देखा 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 स्विच का ठीक उसी प्रकार का कोड है जैसा हम उम्मीद करते हैं:

यहां छवि विवरण दर्ज करें

तो क्या कोई मुझे सुझाव दे सकता है कि केवल एक बार अपने राज्य को चालू या बंद करें। या यह एक बग है या क्या ..?

अपडेट करें

यहाँ यह मेरा डेमो है:

प्रोग्रामेटिक यूआईस्विच जोड़ें

UIBwitch जोड़ने XIB से


1
अभी भी सिम्युलेटर में iOS7.1 में इस बग हो रही है, havent डिवाइस अभी तक की कोशिश की, xcode 5.1.1 चल रहा है
Fonix

3
मुझे 7.1.2 ipad के साथ एक ही समस्या हो रही है
हासी

7
मैं आईओएस 8.0 और 8.1 में यूआईस्विच के साथ एक समान / समान समस्या देख सकता हूं
तिब्बत

2
अभी भी यहाँ 9.1 में। कृपया सभी को Openradar.appspot.com/15555929 का एक डुप्लिकेट दर्ज करें । यह एकमात्र तरीका है जिसे हम निश्चित करने जा रहे हैं।
गिलाउम अलगिस

1
लगता है कि यह 9.3 में वापस आ गया है
बेन लेगियरो

जवाबों:


44

कृपया निम्नलिखित कोड देखें:

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

जवाब के लिए thx जैसा कि मैंने कहा कि मैं दोनों तरह से कोशिश कर रहा था और एक ही परिणाम मिला। atlist मैं जानता हूँ कि swtich प्रोग्रामेटिक के साथ-साथ xib sir से कैसे जोड़ा जाता है।
नितिन गोहेल

12

वही बग यहाँ। मुझे लगता है कि मुझे एक साधारण वर्कअराउंड मिल गया है। हमें बस एक नई का उपयोग करना होगा जो BOOLकि पिछली स्थिति को संग्रहीत करता है UISwitchऔर यदि हमारे IBAction(वैल्यू चेंजेड फायर) में एक स्टेटमेंट यह जांचता है कि स्विच का मूल्य वास्तव में बदल गया है।

previousValue = FALSE;

[...]

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

और कोई अजीब व्यवहार नहीं। आशा करता हूँ की ये काम करेगा।


2
यह सिर्फ कहना चाहिए अगर (mySwitch.on == पिछलेValue)
कीगन जे

12

आप उपयोग कर सकते हैं UISwitchकी .selectedसुनिश्चित करें कि आपके कोड केवल एक बार जब मूल्य वास्तविक परिवर्तन कार्यान्वित करने के लिए संपत्ति। मुझे लगता है कि यह एक महान समाधान है क्योंकि यह उपवर्ग या नई संपत्तियों को जोड़ने से बचता है।

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

और यहाँ यह स्विफ्ट में है:

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

6
मुझे यह सबसे सरल लगता है।
ज़ेकेल

+ 1 इसे इसलिए कि जब मैं टॉगल तर्क को अनदेखा करना चाहता हूं तो यह .tag मान को पॉप्युलेट करने के समान समाधान का उपयोग करने के लिए मुझे प्रेरित करता है। मुझे तर्क को कभी-कभी आग लगाने की आवश्यकता है, दोनों ऊपर और बंद मोड में इसलिए ऊपर पर्याप्त नहीं था।
davidethell

9

यदि आप अपने ऐप में इतने सारे स्विच का उपयोग कर रहे हैं, तो उन सभी जगहों पर कोड को बदलने की समस्या है जहां यूआईस्विच की टी एक्शन विधि को परिभाषित किया गया है। आप कस्टम स्विच बना सकते हैं और घटनाओं को तभी संभाल सकते हैं जब मूल्य बदल जाता है।

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। यह समस्या को हल करेगा और लक्ष्य को केवल एक बार कॉल करेगा जब मूल्य बदल जाएगा


इसने मेरे लिए काम किया। यह आदर्श है कि यह बाहरी कोड को आपके कार्यान्वयन फ़ाइलों में मैन्युअल रूप से नहीं जोड़ा जाता है, क्योंकि यह पुन: प्रयोज्य है और वर्ग कार्यान्वयन के अंदर इसके कार्यान्वयन को छुपाता है। यह सिर्फ अच्छा डिज़ाइन है। यह अच्छा होगा यदि इस उत्तर में अधिक टिप्पणियां हैं, क्योंकि मुझे वास्तव में समझ नहीं आया कि सभी कोड क्यों हैं।
जेम्स सी

धन्यवाद, यह मेरे लिए काम किया। क्या आप कोड को थोड़ा और समझा सकते हैं। @ कोडर
स्वयंभू

7

मुझे कई उपयोगकर्ता मिले जो एक ही मुद्दे का सामना कर रहे हैं इसलिए यह बग हो सकता है UISwitchइसलिए मैंने इसे अभी इसके अस्थायी समाधान के लिए पाया है। मैंने पाया कि एक gitHubकस्टम KLSwitchउपयोग के लिए अब आशा है कि Apple इसे xCode के अगले अपडेट में ठीक कर देगा: -

https://github.com/KieranLafferty/KLSwitch


6

यदि आपको स्विच के मूल्य में तुरंत प्रतिक्रिया करने की आवश्यकता नहीं है, तो परिवर्तन निम्नलिखित हो सकता है:

- (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 11.2 में एक आकर्षण की तरह काम किया। मेरी स्थिति में, इसने 2 घटनाओं को एक पंक्ति में निकाल दिया (स्थिति: बंद, स्वाइपिंग: बंद, पहली घटना: चालू, दूसरी घटना: बंद), इसलिए 0.1s की देरी मेरे लिए पर्याप्त है और उपयोगकर्ता के लिए ध्यान देने योग्य नहीं है।
पॉल सेमियोनोव

3

यह मुद्दा अभी भी iOS 9.3 बीटा के रूप में यहाँ है। यदि आप उपयोगकर्ता को स्विच के बाहर खींचने में सक्षम नहीं होने का बुरा नहीं मानते हैं, तो मुझे लगता है कि मज़बूती .TouchUpInsideसे .ValueChangedकाम करने के बजाय इसका उपयोग करना चाहिए ।


2

मैं अभी भी iOS 9.2 में इसी समस्या का सामना कर रहा हूं

मुझे समाधान मिल गया है और यह दूसरों की मदद कर सकता है

  1. कई बार कॉल की गई विधि का पता लगाने के लिए काउंट वैरिएबल बनाएं

    int switchMethodCallCount = 0;
  2. स्विच मान के लिए बूल मान सहेजें

    bool isSwitchOn = No;
  3. स्विच के मूल्य परिवर्तन विधि में केवल पहली विधि कॉल के लिए इच्छा क्रिया करें। जब स्विच वैल्यू फिर से सेट होता है तो काउंट वैल्यू और .t बूल वैरिएबल वैल्यू को डिफॉल्ट पर सेट करें

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

मैं भी 9.2 में इस मुद्दे का सामना कर रहा हूं। मैंने आपका तर्क लागू किया, और अब यह काम कर रहा है जैसा मैंने इरादा किया था।
निक कोहंर

2

यह समस्या मुझे तब होती है जब मैं अन्य व्यवहारों के लिए स्विच को टाई करता हूं। आम तौर पर चीजों से जाना पसंद नहीं है 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! :)


1

इस प्रकार की समस्या अक्सर ValueChanged के कारण होती है। फ़ंक्शन को चलाने के लिए आपको बटन दबाने की आवश्यकता नहीं है। यह एक स्पर्श घटना नहीं है। हर बार जब आप प्रोग्राम को स्विच ऑन / ऑफ में बदलते हैं, तो वैल्यू बदल जाती है और यह IBAction फ़ंक्शन को फिर से कॉल करता है।

@RoNiT के पास सही उत्तर था:

तीव्र

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

यह ठीक काम करता है और चयनकर्ता फ़ंक्शन को फिर से कॉल नहीं करता है।


0

इसने मेरे लिए काम किया।

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
    self.switch.isOn = true
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.