[英]Swift 2.1 OSx shell commands using NSTask work when run from xcode, but not when exported
I wrote a simple OSx (10.11) application to execute shell commands when a button is pressed.我编写了一个简单的 OSx (10.11) 应用程序来在按下按钮时执行 shell 命令。 It works when I run it from xcode, but when I export the application via "archive", one of the buttons no longer works.当我从 xcode 运行它时它可以工作,但是当我通过“归档”导出应用程序时,其中一个按钮不再起作用。 I don't get an error and I don't get any output either.我没有收到错误,也没有得到任何输出。 I am using absolute paths so I don't understand why it works in xcode but not as an exported application, Nor do I understand why one button works and the other doesn't.我使用的是绝对路径,所以我不明白为什么它在 xcode 中有效,但不能作为导出的应用程序,我也不明白为什么一个按钮有效而另一个无效。
Here is the main function that I am using the make the shell commands这是我使用 make shell 命令的主要功能
func runCommand(path : String, args : [String]) -> (output: [String], error: [String], exitCode: Int32) {
var output : [String] = []
var error : [String] = []
let task = NSTask()
task.launchPath = path
task.arguments = args
let outpipe = NSPipe()
task.standardOutput = outpipe
let errpipe = NSPipe()
task.standardError = errpipe
task.launch()
let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
if var string = String.fromCString(UnsafePointer(outdata.bytes)) {
string = string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
output = string.componentsSeparatedByString("\n")
}
let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
if var string = String.fromCString(UnsafePointer(errdata.bytes)) {
string = string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
error = string.componentsSeparatedByString("\n")
}
//task.waitUntilExit()
let status = task.terminationStatus
return (output, error, status)
}
and here is the button that works:这是有效的按钮:
// Check for configurator 2 app installation
let (output, error, status) = self.runCommand("/bin/bash", args: ["-c", "/bin/ls", "/Applications/Apple Configurator 2.app"])
and here is the button that doesn't:这是没有的按钮:
// Check if the phone is plugged in and paired
let (output, error, status) = self.runCommand("/bin/bash", args: ["-c", "/usr/local/bin/cfgutil", "get", "isPaired"])
What is even more strange, I discovered (through sheer frustration) that if I repeatedly click the button that doesn't work, it will sometimes eventually work.更奇怪的是,我发现(完全出于沮丧)如果我反复单击不起作用的按钮,它有时最终会起作用。
Your issue is the result of two things happening together:您的问题是两件事情同时发生的结果:
you return default values你返回默认值
you don't specify alternative branches for the control flow您没有为控制流指定替代分支
What happens is that it hides potential failures, and leads to code that is very hard to debug, as you experienced.发生的情况是它隐藏了潜在的故障,并导致代码很难调试,正如您所经历的那样。
A possible solution with your existing code is to cover all possible ways, meaning providing else
branches to your if var string = String.fromCString(UnsafePointer(errdata.bytes))
conditions, where you will handle errors.您现有代码的一个可能解决方案是涵盖所有可能的方式,这意味着为您的if var string = String.fromCString(UnsafePointer(errdata.bytes))
条件提供else
分支,您将在其中处理错误。
Thanks to Eric D. I simplified my code and now everything is working.感谢 Eric D。我简化了代码,现在一切正常。
func runCommand(path : String, args : [String]) -> (output: NSString, error: NSString, exitCode: Int32) {
let task = NSTask()
task.launchPath = path
task.arguments = args
let outpipe = NSPipe()
task.standardOutput = outpipe
let errpipe = NSPipe()
task.standardError = errpipe
task.launch()
let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: outdata, encoding: NSUTF8StringEncoding)
let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
let error_output = NSString(data: errdata, encoding: NSUTF8StringEncoding)
task.waitUntilExit()
let status = task.terminationStatus
return (output!, error_output!, status)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.