Skip to content

Instantly share code, notes, and snippets.

@asus4
Created July 3, 2014 17:28
Show Gist options
  • Save asus4/05cd737edfd013520f20 to your computer and use it in GitHub Desktop.
Save asus4/05cd737edfd013520f20 to your computer and use it in GitHub Desktop.
Call shell-script from Objective-C, Swift
//
// ShellScript.h
//
// Created by Koki Ibukuro on 6/18/14.
// Copyright (c) 2014 Koki Ibukuro. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^ShellScriptMessageCallback)(NSString* msg);
@interface ShellScript : NSObject
// class methods
+ (NSString*) doScript:(NSString*)script directory:(NSString*)directory;
// methods
- (void) runScriptAsync:(NSString*)script directory:(NSString*)directory;
- (void) stopScript;
// property
@property (strong, nonatomic) ShellScriptMessageCallback onMessage;
@end
//
// ShellScript.m
//
// Created by Koki Ibukuro on 6/18/14.
// Copyright (c) 2014 Koki Ibukuro. All rights reserved.
//
#import "ShellScript.h"
@interface ShellScript() {
NSTask *_task;
}
@end
@implementation ShellScript
#pragma mark -
#pragma mark Methods
- (id) init {
if(self == [super self]) {
}
return self;
}
- (void) dealloc {
[self stopScript];
}
- (void) runScriptAsync:(NSString *)script directory:(NSString*)directory {
_task = [ShellScript createShellTask:script];
if(directory) {
[_task setCurrentDirectoryPath:directory];
}
NSPipe *out_pipe = [NSPipe pipe];
[_task setStandardOutput:out_pipe];
NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:@selector(onReadData:) name:NSFileHandleReadCompletionNotification object:[out_pipe fileHandleForReading]];
[notificationCenter addObserver:self selector:@selector(onTerminate:) name:NSTaskDidTerminateNotification object:nil];
[[out_pipe fileHandleForReading] readInBackgroundAndNotify];
[_task launch];
}
- (void) stopScript {
[_task terminate];
NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter removeObserver:self name:NSFileHandleReadCompletionNotification object:nil];
[notificationCenter removeObserver:self name:NSTaskDidTerminateNotification object:nil];
}
- (void) onReadData:(NSNotification*)notification {
NSData *data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
if(data != nil && [data length]) {
NSString* msg = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(self.onMessage) {
self.onMessage(msg);
}
[[notification object] readInBackgroundAndNotify];
}
else {
[self stopScript];
}
}
- (void) onTerminate:(NSNotification*)notification {
[self stopScript];
}
#pragma mark -
#pragma mark Static
+ (NSTask*) createShellTask:(NSString*) script {
NSTask* task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/bash"];
[task setArguments:@[@"-c", script]];
return task;
}
+ (NSString*) doScript:(NSString *)script directory:(NSString*)directory {
NSTask *task = [ShellScript createShellTask:script];
NSPipe *out_pipe = [NSPipe pipe];
[task setStandardOutput:out_pipe];
if(directory) {
[task setCurrentDirectoryPath:directory];
}
[task launch];
NSData* data = [[out_pipe fileHandleForReading] readDataToEndOfFile];
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
@end
//-----------
// Simple
let result = ShellScript.doScript("ls -l", directory: NSHomeDirectory())
println(result)
//-----------
// Async
func onMessage(msg:String!) {
print("get message", msg)
}
let shell:ShellScript = ShellScript()
let path = NSHomeDirectory()
shell.runScriptAsync("python -m SimpleHTTPServer 8888", directory:path);
shell.stopScript()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment