Real time NSTask output to NSTextView with Swift
(See Patrick F.'s answer for an update to Swift 3/4.)
You can read asynchronously from a pipe, using notifications.
Here is a simple example demonstrating how it works, hopefully that
helps you to get started:
let task = NSTask()
task.launchPath = "/bin/sh"
task.arguments = ["-c", "echo 1 ; sleep 1 ; echo 2 ; sleep 1 ; echo 3 ; sleep 1 ; echo 4"]
let pipe = NSPipe()
task.standardOutput = pipe
let outHandle = pipe.fileHandleForReading
outHandle.waitForDataInBackgroundAndNotify()
var obs1 : NSObjectProtocol!
obs1 = NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification,
object: outHandle, queue: nil) { notification -> Void in
let data = outHandle.availableData
if data.length > 0 {
if let str = NSString(data: data, encoding: NSUTF8StringEncoding) {
print("got output: \(str)")
}
outHandle.waitForDataInBackgroundAndNotify()
} else {
print("EOF on stdout from process")
NSNotificationCenter.defaultCenter().removeObserver(obs1)
}
}
var obs2 : NSObjectProtocol!
obs2 = NSNotificationCenter.defaultCenter().addObserverForName(NSTaskDidTerminateNotification,
object: task, queue: nil) { notification -> Void in
print("terminated")
NSNotificationCenter.defaultCenter().removeObserver(obs2)
}
task.launch()
Instead of print("got output: \(str)")
you can append the received
string to your text view.
The above code assumes that a runloop is active (which is the case
in a default Cocoa application).
How to launch application and bring it to front using Cocoa api?
To launch an application :
[[NSWorkspace sharedWorkspace] launchApplication:@"/Applications/Safari.app"];
To activate an app :
NSRunningApplication* app = [NSRunningApplication
runningApplicationWithProcessIdentifier: PID];
[app activateWithOptions: NSApplicationActivateAllWindows];
// or
NSArray* apps = [NSRunningApplication
runningApplicationsWithBundleIdentifier:@"com.bla.blah"];
[(NSRunningApplication*)[apps objectAtIndex:0]
activateWithOptions: NSApplicationActivateAllWindows];
Obtain Model Identifier string on OS X
You can use sysctl
#import <Foundation/Foundation.h>
#import <sys/sysctl.h>
NSString *ModelIdentifier()
{
NSString *result=@"Unknown Mac";
size_t len=0;
sysctlbyname("hw.model", NULL, &len, NULL, 0);
if (len) {
NSMutableData *data=[NSMutableData dataWithLength:len];
sysctlbyname("hw.model", [data mutableBytes], &len, NULL, 0);
result=[NSString stringWithUTF8String:[data bytes]];
}
return result;
}
Related Topics
Swift - Rotate Gesture and Rotation Increments of 90 Degrees
How to Put a View with Loadmore Button in UItableview After The Cell
How to Decorate Siesta Request with an Asynchronous Task
How to Show an Alert in Swift UIalertview Not Working
Firebase - Swift 4: Message Sent But Not Received
Swiftui Tabview with List Not Refreshing After Objected Deleted From/Added to Core Data
How to Detect Encoding in Data Based on a String
Qlpreviewcontroller Showing File Then Going Blank in Swiftui
Connecting Avaudiosourcenode to Avaudiosinknode Does Not Work
Having Trouble with Musickit Sample App Provided by Apple
External Library Usage in Xcode
When Creating Thread Safe Reads in Swift, Why Is a Variable Create Outside The Concurrent Queue
Swift Execute Command Line Command in Sandbox Mode
Trouble Passing Array Through Prepareforsegue
How to Use Protocols for Stucts to Emulate Classes Inheritance