ブール値フラグを含むモデル オブジェクトがあります。UISwitch を使用してフラグの値を表示したい。値は次の 2 つの方法で変更できます。
- まずユーザーがスイッチを切り替えます。そのために UIControlEventTouchUpInside を登録します。UIControlEventValueChanged も試しましたが、まったく同じ効果があります。
- 第二に、何らかの外部状態の変化によるものです。タイマーを使用してその状態の変化をチェックし、それに応じてスイッチの 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