使用NSTask的Swift 2.1 OSx shell命令在从xcode运行时工作,但在导出时不工作

时间:2016-03-07 21:34:26

标签: xcode swift macos shell nstask

我编写了一个简单的OSx(10.11)应用程序,用于在按下按钮时执行shell命令。当我从xcode运行它时它可以工作,但是当我通过" archive"导出应用程序时,其中一个按钮不再有效。我没有收到错误,也没有收到任何输出。我使用的是绝对路径,所以我不明白为什么它在xcode中工作但不能作为导出的应用程序工作,我也不明白为什么一个按钮工作而另一个按钮不工作。

这是我使用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)
}

这是一个有效的按钮:

      // Check for configurator 2 app installation
    let (output, error, status) = self.runCommand("/bin/bash", args:  ["-c", "/bin/ls", "/Applications/Apple Configurator 2.app"])

这里是没有按钮的按钮:

        // 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"])

更奇怪的是,我发现(通过纯粹的挫折感)如果我反复点击不起作用的按钮,它有时最终会起作用。

2 个答案:

答案 0 :(得分:1)

你的问题是两件事发生在一起的结果:

  • 您返回默认值

  • 您没有为控制流指定替代分支

它会隐藏潜在的失败,导致代码很难调试,就像您所经历的那样。

现有代码的可能解决方案是涵盖所有可能的方式,即在else条件中提供if var string = String.fromCString(UnsafePointer(errdata.bytes))分支,您将处理错误。

答案 1 :(得分:0)

感谢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)
}