タイトルの文章だとちょっとわかりにくいと思うので、困ってたことと解決策を書きます。
困っていた状況
- 自分のOSXアプリを起動中、他のアプリがアクティブになっている状態で、自分のアプリにマウスイベント(例:クリック)を加える
- 最初のマウスイベントでは自分のアプリがアクティブになるけど、Viewのイベントは発生しない。
- 以降のマウスイベントではViewのイベントは発生する。
ウィンドウが非アクティブな状態でもマウスのファーストタッチでイベント発生する方法ないかなーと思っていたら簡単に解決できる方法がありました。
解決策
マウスイベントを受け取りたいNSViewのサブクラスにacceptsFirstMouse:
メソッドを実装し、戻り値をtrue
にする。
サンプル
作ったもの
acceptsFirstMouse:
の戻り値が true
/ false
なSampleViewをそれぞれ作ります。
各ViewはmouseDown:
イベントを受け取るとアラートを表示します。
ソース
sample.swift
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let view = SampleView(frame: CGRectMake(100,100,100,100))
let view2 = SampleView2(frame: CGRectMake(250,100,100,100))
self.view.addSubview(view)
self.view.addSubview(view2)
}
}
class SampleView: NSView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
NSColor.redColor().set()
NSRectFill(dirtyRect)
}
override func mouseDown(theEvent: NSEvent) {
let alert = NSAlert()
alert.messageText = "alert!"
alert.runModal()
}
override func acceptsFirstMouse(theEvent: NSEvent?) -> Bool {
return true
}
}
class SampleView2: NSView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
NSColor.blueColor().set()
NSRectFill(dirtyRect)
}
override func mouseDown(theEvent: NSEvent) {
let alert = NSAlert()
alert.messageText = "alert!"
alert.runModal()
}
override func acceptsFirstMouse(theEvent: NSEvent?) -> Bool {
return false
}
}
結果
SampleView(赤いView)は非アクティブな状態でもクリックするとアラートが表示されます。
SampleView2(青いView)は非アクティブな状態からクリックするとアラートが表示されません。
アクティブになった状態でクリックするとアラートが表示されます。