Swift: forward keystrokes to a different process
One of the comments suggested that permissions might be the cause, and it was.
My problem was resolved by going to the Capabilities section of my project and disabling App Sandboxing, which was enabled by default.
Keep in mind that App Sandboxing is a requirement for your app to be on the App Store (reference)
Send keypress to specific window on Mac
Demo in swift
, using
$ swift --version
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin17.7.0
simple example code sendspace.swift
import Foundation
let src = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
let kspd = CGEvent(keyboardEventSource: src, virtualKey: 0x31, keyDown: true) // space-down
let kspu = CGEvent(keyboardEventSource: src, virtualKey: 0x31, keyDown: false) // space-up
let pids = [ 24834, 24894, 24915 ]; // real PID-s from command 'ps -ax' - e.g. for example 3 different processes
for i in 0 ..< pids.count {
print("sending to pid: ", pids[i]);
kspd?.postToPid( pid_t(pids[i]) ); // convert int to pid_t
kspu?.postToPid( pid_t(pids[i]) );
}
After running the code: swift sendspace.swift
(from the Terminal) all 3 processes with defined PIDs will get the space keypress, while the Terminal is still the foreground app.
Implement a Swift protocol by automatically mapping method calls to keys in a dictionary
That kind of dynamic handling of arbitrary messages at runtime can only be done in Objective-C. For one thing, calls to pure Swift methods don't even go through the Objective-C dynamic dispatch mechanism. So it would have to be an @objc
method, and the forwardInvocation:
logic will have to be implemented in Objective-C.
Send a keyboard shortcut to a Mac OS X Window
One way to do this is embedding Applescript in your Objective-C application.
For example executing this apple script, sends Command + M to System Events
application:
tell application "System Events" to keystroke "m" using {command down}
You can embed the script above in your Cocoa application with something like this:
//AppControler.h
#import <Cocoa/Cocoa.h>
@interface AppController : NSObject {
NSAppleScript *key;
}
-(IBAction)sendkeys:(id)sender;
@end
//AppControler.m
#import "AppController.h"
@implementation AppController
-(IBAction)sendkeys:(id)sender
{
NSAppleScript *key = [[NSAppleScript alloc] initWithSource:@"tell application "System Events" to keystroke "m" using {command down}"];
[start executeAndReturnError:nil];
}
@end
distinguish between different instances or windows of a process and find their PID instead of their owner PID to send input event in macOS?
This activates each window in TextEdit and sends a space keystroke.
activate application "TextEdit"
tell application "System Events"
tell application process "TextEdit"
repeat with theWindow in windows
perform action "AXRaise" of theWindow
keystroke " "
end repeat
end tell
end tell
But to note how this would work without pressing keys, the following appends "A" to all the currently open documents without bringing anything to the foreground or interfering with the user's input.
tell application "TextEdit"
repeat with theDocument in documents
set text of theDocument to (text of theDocument) & "A"
end repeat
end tell
Whenever possible, you want things like this rather than sending keystrokes.
Swift map nested dictionary to swap outer and inner keys
A possible way is to use reduce(into:_:)
:
With sample:
let rates: [String: [String: Double]] = ["2021-11-14": ["CAD": 1.1,
"USD": 1.0,
"EUR": 0.9],
"2021-11-15": ["CAD": 1.11,
"USD": 1.01,
"EUR": 0.91]]
This should do the trick:
let target = rates.reduce(into: [String: [String: Double]]()) { partialResult, current in
let date = current.key
let dayRates = current.value
dayRates.forEach { aDayRate in
var currencyRates = partialResult[aDayRate.key, default: [:]]
currencyRates[date] = aDayRate.value
partialResult[aDayRate.key] = currencyRates
}
}
For the logic, we iterate over each elements of rates
.
For each [CurrencyCode: Amount], we iterate on them, and set them to partialResult
(which at the end of the inner loop of reduce(into:_:)
will be the finalResult
, ie the returned value).
Outputs for print(rates)
& print(target)
(I just formatted them to make them easier to read):
$> ["2021-11-14": ["CAD": 1.1, "EUR": 0.9, "USD": 1.0],
"2021-11-15": ["USD": 1.01, "EUR": 0.91, "CAD": 1.11]]
$> ["EUR": ["2021-11-14": 0.9, "2021-11-15": 0.91],
"USD": ["2021-11-15": 1.01, "2021-11-14": 1.0],
"CAD": ["2021-11-14": 1.1, "2021-11-15": 1.11]]
GeoFire observeReady gets executed prematurely in Swift
What you're seeing is expected behavior. The observeReady
is guaranteed to fire after all the corresponding observe(.keyEntered)
have been called. You can verify this with some simple logging statements:
query.observe(.keyEntered) { (key: String!, venueLocation: CLLocation!) in
print(".keyEntered")
}
query.observeReady {
print(".observeReady")
}
When you run this it will print:
.keyEntered
.keyEntered
...
.observeReady
That is in line with how the API is supposed to work. But in the .keyEntered
you are loading additional data from Firebase, which happens asynchronously. And those calls may indeed complete after the .observeReady
has fired.
So you will need to implement the necessary synchronization yourself. A simple way to detect if you have loaded all the additional data, is to keep a count of all the keys for which you still need to load data. So you +1
that every time you add a key, and -1
every time you've loaded the venue data:
let venuesToLoadCount = 0
query.observe(.keyEntered) { (key: String!, venueLocation: CLLocation!) in
venuesToLoadCount = venuesToLoadCount + 1
self.REF_VENUES.child(key).observeSingleEvent(of: .value, with: { (snapshot) in
venuesToLoadCount = venuesToLoadCount - 1
if venuesToLoadCount == 0 {
print("All done")
}
}
}
query.observeReady {
if venuesToLoadCount == 0 {
print("All done")
}
}
Related Topics
Does Realm Support Computed Property in Swift
<Unknown>:0: Error: Opening Import File for Module 'swift': Not a Directory
Addperiodictimeobserver Is Not Called Every Millisecond
Could Not Find an Overload for "Init" That Accepts The Supplied Arguments (Swift)
Running Xcode Docc Documentation via Apache Locally on Macos
Passing Data Between 2 View Controllers in Swift
How to Separate The Date and Time Components of Nsdate() in Swift
Extension for Average to Return Double from Numeric Generic
Is There a Simple Way to Test If You Match One of a Set of Enumerations
Loading Image from Remote Url Asynchronously in Swiftui Image Using Combine's Publisher
Swift: Forward Keystrokes to a Different Process
Nsextensionpointidentifier Error Only on Real Device
How to Put Gamecenter on Application with Swift
iOS9 Filemanager File Permissions Change