管理事件循环
func nextEvent(matching: NSEvent.EventTypeMask, until: Date?, inMode: RunLoop.Mode, dequeue: Bool) -> NSEvent?
返回根据给定的matching匹配到的下一个事件。如果在until超时时间之前没有找到,返回nil。
声明
@MainActor func nextEvent(matching mask: NSEvent.EventTypeMask, until expiration: Date?, inMode mode: RunLoop.Mode, dequeue deqFlag: Bool) -> NSEvent?
参数
mask
包含一个或多个指明返回事件类型的常量标志。NSEvent类的常量部分定义了你可以创建这个mask使用的常量(我数了数,大概有32个常量,包含鼠标移动,鼠标左键按下、抬起,鼠标右键按下、抬起等等)。方法discardEvents(matching:before:)同样也列出了几个常量。
expiration
当前事件请求的超时时间。此参数设置为nil跟使用distantPast方法返回的日期对象是一样的。
mode
规定在哪个run loop模式下寻找事件。当APP等待事件的时候,你指定模式同样决定触发哪些定时器或者run loop观察者。
deqFlag
如果希望事件从队列中移除,则设定为true。
返回值
与mask参数中定义的其中一个类型匹配的事件对象。
详情
你可以使用此方法缩短正常事件调度循环并获取你自己的事件。例如:你可能想在鼠标点击时,响应鼠标点击的事件。(在这样的例子中,你需要传递一个合适的事件类型,比如鼠标拖动、鼠标抬起,给mask参数,并指定NSEventTrackingRunLoopMode参数的run loop模式)。没有与给定事件类型中的其一匹配成功的事件,会保留在队列中。
你可以指定AppKit中定义的run-loop模式,或者你程序中使用的自定义run-loop模式。
AppKit定义的run-loop模式如下:
- NSDefaultRunLoopMode
- NSEventTrackingRunLoopMode
- NSModalPanelRunLoopMode
- NSConnectionReplyMode
系统要求
macOS
func discardEvents(matching: NSEvent.EventTypeMask, before: NSEvent?)
移除给定的事件之前所有与mask匹配成功的事件。
声明
@MainActor func discardEvents(matching mask: NSEvent.EventTypeMask, before lastEvent: NSEvent?)
参数
mask
包含一个或多个标志,指明需要移除的事件。NSEvent类中的常量部分定义了你可以创建这个mask的常量。下边的详情部分也列出了一部分通常使用的常量。
lastEvent
一个基准事件,用来指明哪些事件需要移除。发生在这个事件之前的事件将会移除,这个事件之后的事件不会被移除。
详情
用这个方法忽略基准事件之前的事件。例如,假设你的APP中有一个跟踪循环,在用户松开鼠标按键时,退出这个循环。你能会用到该方法,用NSAnyEventMask作为mask参数,用结束mouse-up事件作为lastEvent参数,移除在你的跟踪循环中,鼠标移动时的所有事件。传递mouse-up事件给lastEvent参数,确保发生在mouse-up之后的事件(也就是说mouse-up事件之后出现在队列中的事件)不会被移除。
备注:
通常来说,这个消息应该发送给NSWindow,而不是APP对象。丢弃一个窗口的事件,仅清除当前窗口的事件,对其他窗口没有影响。
对于mask参数,你可以将以下的事件常量添加在一起:
- NSLeftMouseDownMask
- NSLeftMouseUpMask
- NSRightMouseDownMask
- NSRightMouseUpMask
- NSMouseMovedMask
- NSLeftMouseDraggedMask
- NSRightMouseDraggedMask
- NSMouseEnteredMask
- NSMouseExitedMask
- NSKeyDownMask
- NSKeyUpMask
- NSFlagsChangedMask
- NSPeriodicMask
- NSCursorUpdateMask
- NSAnyEventMask
这个方法也可以在子线程中调用。子线程中传递的事件,在主线程中冒泡出现。
冒泡算法:通过对待排序序列从前向后(从下标较小的元素开始),依次对相邻两个元素的值进行两两比较,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就如果水底下的气泡一样逐渐向上冒
系统要求
macOS
var currentEvent: NSEvent?
APP从事件队列检索到的最后一个事件。
声明
@MainActor var currentEvent: NSEvent? { get }
详情
APP单例对象接收到事件,将它们转发至受影响的NSWindow,然后由NSWindow分发给它的view层级中的对象。用这个属性获取APP最后处理的事件。
系统要求
macOS
var isRunning: Bool
指示主事件循环是否运行的布尔值。
声明
@MainActor var isRunning: Bool { get }
详情
如果主循环运行中,此属性为true,如果没有运行,则为false。调用stop(_:)方法,将此属性设置为false。
系统要求
macOS
func run()
启动主事件循环。
声明
@MainActor func run()
详情
在收到stop(_:)和terminate(_:)消息之前,循环将会一直持续。在循环的每次迭代中,来自窗口服务器的下一个可用事件,将会保存,并且会通过sendEvent(_:)分发个NSApp。
创建NSApplication对象之后,main方法应该加载你的APP的主nib文件,并且通过给NSApplication对象发送一个run()消息,来启动事件循环。如果你是用Xcode创建的Cocoa程序,main方法已经自动实现了。
系统要求
macOS
func finishLaunching().
激活APP,打开用户默认的NSOpen指定的文件,取消APP图标高亮状态。
声明
@MainActor func finishLaunching()
详情
run()方法在开始事件循环之前调用这个方法。在这个方法开始时,会给默认通知中心发送一个willFinishLaunchingNotification通知。如果重写了finishLaunching()方法,需要在子类中实现这个父类方法。
系统要求
macOS
func stop(Any?)
停止主事件循环
声明
@MainActor func stop(_ sender: Any?)
参数
sender
发送此消息的对象。
详情
这个方法通知APP,你想在当前NSEvent对象执行完成之后,马上退出当前run loop。这个方法不是强制退出当前run loop。而是设置一个标记(flag),“立了一个flag”,只有当现存的事件对象完成调度时,APP才会检查flag是否达成。例如,你可以从响应按钮点击事件的方法中调用此方法,或者从NSResponder类定义的众多方法中的一个中调用此方法。然而,从定时器或者run-loop监听者中调用此方法,通常不会停止run loop。因为它们没有发送NSEvent对象。
如果你从运行在主run loop中的事件处理句柄中调用这个方法,APP会退出run()方法,从而将控制权移交给main()函数。如果你从一个modal 事件循环中调用这个方法,将会退出这个modal事件循环,而不是主事件循环。
系统要求
macOS
func sendEvent(NSEvent)
调度一个事件给其他对象。
声明
@MainActor func sendEvent(_ event: NSEvent)
参数
event
需要调度的事件。
详情
尽管你想重写此方法实现对每个事件执行某些操作,但是很少需要你直接调用sendEvent(_:)方法。sendEvent(_:)消息从主事件循环(run()方法)发出。sendEvent(_:)是一个调度事件给合适的响应者的方法--NSAPP去处理APP事件,NSWindow去处理窗口相关的事件,鼠标和键盘事件转移个适当的NSWindow对象进一步调度。
系统要求
macOS
func postEvent(NSEvent, atStart: Bool)
将给定的事件添加到接受者的事件队列中。
声明
@MainActor func postEvent(_ event: NSEvent, atStart: Bool)
参数
event
要发送到事件队列的事件对象。
atStart
true:添加到事件队列的前边。false:返回队列的后边。
详情
此方法也可以在子线程中调用。在子线程中发布的事件在主线程中冒泡出现。
系统要求
macOS