How to Properly Test Against Certain Values in Nseventmodifierflags via Swift

How to properly test against certain values in NSEventModifierFlags via Swift?

I have found a solution, here I check for the shift key:

override func flagsChanged(with event: NSEvent)
{
if event.modifierFlags.contains(.shift)
{
// shift pressed
}
if event.modifierFlags.contains(.shift) == false
{
// shift released
}
}

Checking keyDown event.modifierFlags yields error

Apple's documentation indicates that you simply and the modifier flags

The documentation is still referring to C and Objective-C. Swift uses OptionSetType, which does not use bitwise operators for checking flags.

Instead, use the contains() method to check for one or more flags:

    if theEvent.modifierFlags.contains(.CommandKeyMask) {
NSLog("command key down")
}

if theEvent.modifierFlags.contains(.AlternateKeyMask) {
NSLog("option key down")
}

if theEvent.modifierFlags.contains([.CommandKeyMask, .AlternateKeyMask]) {
NSLog("command and option keys down")
}

To check for a single key, use intersect to filter out any unwanted flags, then use == to check for a single flag:

    let modifierkeys = theEvent.modifierFlags.intersect(.DeviceIndependentModifierFlagsMask)

if modifierkeys == .CommandKeyMask {
NSLog("Only command key down")
}

How can I detect that the Shift key has been pressed?

From the Cocoa event handling guide:

The flagsChanged: method can be useful for detecting the pressing of modifier keys without any other key being pressed simultaneously. For example, if the user presses the Option key by itself, your responder object can detect this in its implementation of flagsChanged:.

More details can be found here.

The documentation for NSResponder also states the following:

flagsChanged:

Informs the receiver that the user has pressed or released a modifier key (Shift, Control, and so on).

-- (void)flagsChanged:(NSEvent *)theEvent

Swift: masks as type properties

This is from an earlier Xcode 6 beta, the correct answer now (Xcode 7/Swift 2) is https://stackoverflow.com/a/32004398/669586


The following is possible:

if (theEvent.modifierFlags & NSEventModifierFlags.CommandKeyMask).value != 0 {

because there is a definition of & for RawOptionSet

func &<T : RawOptionSet>(a: T, b: T) -> T

However, note that RawOptionSet also implements LogicValue, so the following is possible, too:

if theEvent.modifierFlags & NSEventModifierFlags.CommandKeyMask {

Although I consider the first solution to be a bit more clear for the readers

Checking bitmask in Swift

keyEquivalentModifierMask is a Int, whereas NSEventModifierFlags.CommandKeyMask is an enum-like with UInt raw value, so you have to read the rawValue out of it and convert keyEquivalentModifierMask to Uint:

if UInt(button.keyEquivalentModifierMask) & NSEventModifierFlags.CommandKeyMask.rawValue > 0 {
}

Simple Callback with MASShortcut using Swift

There are a few issues here. Before fixing them you should make sure that you have MASShortcut 2.1.2 installed (you can see this in your Podfile.lock). If you don't you should run pod update to get the newest version.

Another potential issue with you testing this is your shortcut conflicting with OS X default shortcuts. In your current example Command+Option+Space is bound to opening a Finder window and selecting the search field. If you have this disabled that's fine, otherwise I would recommend adding Control to your test case.

So there are a few issues with your code so far. First off I would recommend changing your keyMask declaration a bit to:

let keyMask: NSEventModifierFlags = .CommandKeyMask | .ControlKeyMask | .AlternateKeyMask

This way Swift can infer the type and you only have to have NSEventModifierFlags once (notice that I added the .ControlKeyMask here for my comment above).

A cool part about enums in Swift is that you can call rawValue on them. In this case the rawValue of NSEventModifierFlags is a UInt which will fix your type problem when creating your shortcut.

Now your keyCode argument must be a UInt as well. So you can pull this out into a temporary value:

let keyCode = UInt(kVK_Space)

In Swift, methods that look like class level initializers are actually turned in to Swift initializers. So in this case, you're trying to call a class method called shortcutWithKeyCode:modifierFlags: when Swift has actually turned this into an initializer. So you can create your shortcut like this:

let shortcut = MASShortcut(keyCode: keyCode, modifierFlags: keyMask.rawValue)

Note the rawValue call to convert our modifier flags into a UInt.

Finally, the API to register this shortcut globally is actually a method on MASShortcutMonitor. In your bridging header where you have:

#import <MASShortcut/MASShortcut.h>

You'll have to add a new import to get this API. The new one is:

#import <MASShortcut/MASShortcutMonitor.h>

Now you can register your shortcut:

MASShortcutMonitor.sharedMonitor().registerShortcut(shortcut, withAction: callback)

And your all set. Your callback function was already setup correctly!

One last thing. I would recommend removing your shortcut in applicationWillTerminate: like this:

MASShortcutMonitor.sharedMonitor().unregisterAllShortcuts()

How to ask a remote windows machine to automatically launch an application?

If you're developing an application that should always be running on the server, you probably need to implement it as a Windows service. For C#, see the classes in the System.ServiceProcess namespace -- you will need to inherit from ServiceBase.

Alternatively, you can set the program to be run as a scheduled task on boot. See the Task Scheduler API to do this.

How Can I get keyboard input in a SpriteKit Game?

The easiest way I know is to implement the keyDown method in your SKScene (and not directly in the AppDelegate). You don't have to subclass anything.

- (void)keyDown:(NSEvent *)event {
[self handleKeyEvent:event keyDown:YES];
}

- (void)keyUp:(NSEvent *)event {
[self handleKeyEvent:event keyDown:NO];
}

Then use the method handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp to check which key has been pressed :

- (void)handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp {
// First check the arrow keys since they are on the numeric keypad.
if ([event modifierFlags] & NSNumericPadKeyMask) { // arrow keys have this mask
NSString *theArrow = [event charactersIgnoringModifiers];
unichar keyChar = 0;
if ([theArrow length] == 1) {
keyChar = [theArrow characterAtIndex:0];
switch (keyChar) {
case NSUpArrowFunctionKey:
self.defaultPlayer.moveForward = downOrUp;
break;
case NSLeftArrowFunctionKey:
self.defaultPlayer.moveLeft = downOrUp;
break;
case NSRightArrowFunctionKey:
self.defaultPlayer.moveRight = downOrUp;
break;
case NSDownArrowFunctionKey:
self.defaultPlayer.moveBack = downOrUp;
break;
}
}
}

// Now check the rest of the keyboard
NSString *characters = [event characters];
for (int s = 0; s<[characters length]; s++) {
unichar character = [characters characterAtIndex:s];
switch (character) {
case 'w':
self.defaultPlayer.moveForward = downOrUp;
break;
case 'a':
self.defaultPlayer.moveLeft = downOrUp;
break;
case 'd':
self.defaultPlayer.moveRight = downOrUp;
break;
case 's':
self.defaultPlayer.moveBack = downOrUp;
break;
case ' ':
self.defaultPlayer.fireAction = downOrUp;
break;
}
}
}

I took this code from the Apple SpriteKit Adventure game. I found it very usefull to learn SpriteKit :)



Related Topics



Leave a reply



Submit