CookieClicker.m
@interface CookieClicker
@property (nonatomic) NSTimer *timer; // 一定間隔でクリックイベントを発行するタイマー
@property (nonatomic) id eventMonitor; // Esc キー押下イベントを監視するモニター
@end
@implementation CookieClicker
// マウスカーソルの位置を1秒間に50クリックする
- (IBAction)bakeMoreCookies:(id)sender
{
// タイマーが稼働中なら何もしない
if (self.timer) return;
// Esc キーの監視を開始する:押されたらタイマーを止める
self.eventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) {
if (event.keyCode == 53 /* Esc */) {
[self ceaseFire];
}
}];
// 0.02秒ごとに tick: メソッドを呼ぶタイマーを稼動させる
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}
// カーソルの位置をクリックする
- (void)tick:(NSTimer *)timer
{
// 空のイベントオブジェクトを作って現在のマウスカーソルの位置を取得する
CGEventRef event = CGEventCreate(NULL);
CGPoint location = CGEventGetLocation(event);
CFRelease(event);
// マウス左ボタンのダウンイベントとアップイベントを発行する
CGEventRef mouseDown = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, location, 0);
CGEventRef mouseUp = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, location, 0);
CGEventPost(kCGHIDEventTap, mouseDown);
CGEventPost(kCGHIDEventTap, mouseUp);
CFRelease(mouseDown);
CFRelease(mouseUp);
}
// クリックを中止する
- (void)ceaseFire
{
// タイマーを止める
[self.timer invalidate];
self.timer = nil;
// Esc キーの監視を止める
[NSEvent removeMonitor:self.eventMonitor];
self.eventMonitor = nil;
}
@end