UISwitch有时不发送UIControlEvents

Ber*_*ber 1 objective-c ios ios5

我有一个包含布尔标志的模型对象。我想使用UISwitch显示标志的值。该值可以通过两种方式更改:

  1. 首先由用户通过拨动开关。我为此注册了UIControlEventTouchUpInside。我还尝试了UIControlEventValueChanged –它具有完全相同的效果。
  2. 其次是由一些外部状态改变。我使用计时器来检查状态更改,并相应地设置开关的on属性。

但是,在计时器方法中设置开关的值具有以下效果:即使用户触摸了开关,有时也不会触发touchUpInside操作。

因此,我面临以下问题:如果在外部更改状态时在计时器中设置开关状态,则会从用户那里释放一些状态更改。如果我不使用计时器,则会从用户那里获得所有状态更改。但是,我想念所有外部状态的变化。

现在我的想法已经用完了。如何在模型中同时获得两种类型的状态变化并将其正确反映在开关视图中,从而实现所需的目标?

这是显示问题的最小示例。我已经用一个简单的布尔标志替换了模型对象,并且在计时器中我根本不更改标志,我只是调用setOn:animated:。我计算动作方法的调用次数。这样,我可以轻松找出错过了多少次触摸:

#import "BPAppDelegate.h"
#import "BPViewController.h"

@implementation BPAppDelegate {
    NSTimer *repeatingTimer;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    BPViewController *viewController = [[BPViewController alloc] init];
    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];
    [self startTimer];
    return YES;
}

- (void) startTimer {
    repeatingTimer = [NSTimer scheduledTimerWithTimeInterval: 0.2
                                                      target: self.window.rootViewController
                                                    selector: @selector(timerFired:)
                                                    userInfo: nil
                                                     repeats: YES];
}

@end


#import "BPViewController.h"

@implementation BPViewController {
    UISwitch *uiSwitch;
    BOOL value;
    int count;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    value = true;
    uiSwitch = [[UISwitch alloc] init];
    uiSwitch.on = value;
    [uiSwitch addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:uiSwitch];
}

- (void)touchUpInside: (UISwitch *)sender {
    count++;
    value = !value;
    NSLog(@"touchUpInside: value: %d, switch: %d, count: %d", value, sender.isOn, count);
}

- (void) timerFired: (NSTimer*) theTimer {
    NSLog(@"timerFired: value: %d, switch: %d, count: %d", value, uiSwitch.isOn, count);
    // set the value according to some external state. For the example just leave it.
    [uiSwitch setOn:value animated:false];
}

@end
Run Code Online (Sandbox Code Playgroud)

CSm*_*ith 5

使用UIControlEventValueChanged以确定何时开关已打开(编程或由用户)。不要使用touchUpInside。也touchUpInside不会在用户的正常工作拖动的UISwitch。

另外,不要复制UISwitch已经维护的属性(例如您的value属性)(即“ on”属性)...它是多余的,只会给您带来麻烦