我有一个模型对象,其中包含一个布尔标志。我想使用 UISwitch 显示标志的值。该值可以通过两种方式更改:
- 首先由用户通过切换开关。我为此注册了 UIControlEventTouchUpInside。我还尝试了 UIControlEventValueChanged - 它具有完全相同的效果。
- 其次是一些外部状态的变化。我使用计时器来检查该状态更改并相应地设置开关的 on 属性。
但是,在 timer 方法中设置开关的值会导致即使用户触摸了开关,有时也不会触发 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