S3Sync
以前、S3にバケットを作成してGlacierアーカイブを行う手順を確認したが、この仕組みを利用してMacの任意のディレクトリをS3 Glacierと自動的に同期するアプリケーション「S3Sync」を作ってみた。Macのスリープを検知すると同期を始めるので、寝ている間にラクラク同期できる。
といってもこのアプリ、単にNSTaskを使ってシステムコマンドを実行しているだけのアプリなので、任意のコマンドを自由に実行することができる。ステータスバーに常駐しているアプリなので、作業の邪魔にもならない。
スリープ検知
スリープ検知をするには、NSWorkspace ClassのNSWorkspaceWillSleepNotification属性を使う。
func applicationDidFinishLaunching(aNotification: NSNotification) { // スリープ検知 NSWorkspace.sharedWorkspace().notificationCenter.addObserver(self, selector: #selector(self.receiveSleepNotification(_:)), name: NSWorkspaceWillSleepNotification, object: nil) } func receiveSleepNotification(notification: NSNotification){ // スリープ実行時に行う処理 }
システムコマンドの実行
システムコマンドは、NSTask Classから実行することが可能である。
NSTaskは、実行したシステムコマンドの出力結果を取り出すことも可能だが、readDataToEndOfFile()を使うとブロッキング処理が発生してしまうので、dispatch_async()を使って非同期に順次出力処理していく必要がある。
let task = NSTask() // 実行コマンドをフルパスで指定 task.launchPath = "/usr/local/bin/aws " // パラメータを配列形式で指定 task.arguments = ["-h", "hogehoge"] // 標準出力をパイプに渡す let pipe: NSPipe = NSPipe() task.standardOutput = pipe let stdoutHundle = pipe.fileHandleForReading // 非同期処理 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), { var dataRead = stdoutHundle.availableData while(dataRead.length > 0){ let stringRead = NSString(data: dataRead, encoding: NSUTF8StringEncoding) if let output = stringRead { // 出力結果処理 } dataRead = stdoutHundle.availableData } // コマンドの実行 task.launch()
NSTaskは、suspend()やterminate()を使って、途中で処理を停止したり、完全に終了してしまったりすることができる。suspend()で中断した処理は、resume()で再開することができる。また、タスクが実行中にも関わらず再度launch()を実行してしまうと、下記の実行エラーが発生してしまう。
task already launched
通知の送信
本アプリは、コマンド実行毎にMacの通知センターに実行状況を通知する。
Macの通知センターに通知を送信するには、NSUserNotificationCenter Classを使う。送信する通知には、「タイトル」「サブタイトル」の他に様々な項目を設定することが可能である。
// NSUserNotificationCenterDelegateが必要 class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate { func deliverNotification(title : String, subtitle : String, informativeText: String){ // AppDelegate Classにデリゲードを指定 NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self let notification = NSUserNotification() notification.title = title notification.subtitle = subtitle notification.informativeText = informativeText notification.contentImage = NSImage(named: "MainIcon") notification.userInfo = ["title" : "タイトル"] NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification(notification) } }
ログを保存するディレクトリの指定
本アプリは、実行ログをファイルに保存することができる。
Macでディレクトリやファイルを開くする際は、NSOpenPanel Classを利用する。
また、保存の際はNSSavePanel Classというクラスも用意されている。
// MARK: ディレクトリ選択画面 let panel = NSOpenPanel() // ファイル選択の可否 panel.canChooseFiles = false // ディレクトリ選択の可否 panel.canChooseDirectories = true // 複数選択の可否 panel.allowsMultipleSelection = false panel.beginWithCompletionHandler({(num) -> Void in if num == NSModalResponseOK { // ディレクトリ・ファイル決定時の処理 } })
常駐アプリ
ステータスバーに常駐するアプリを作成するためには、Project > TARGET > Info > Custom OS X Application Target Propertiesから、Application is agent (UIElement)をYESに設定する。
StoryBoardのTips
- 常駐アプリであっても、Main Menu > Edit がないと、TextFieldの Shortcut Keyが使えない。