每次用不同的参数重复两次过程

repeating process twice with different arguments each time

我对编码还是很陌生 Swift。请原谅我毫无疑问笨拙的代码。

我正在尝试 运行 一个带有来自主资源包的 ffprobe 的进程。实际上,我需要 运行 两次,每次使用不同的参数,一次是为了获取我正在输入的音频文件的持续时间,一次是为了获取完整的输出,以便我可以解析它以获得一些花絮我无法像文件持续时间那样在单个参数中隔离的数据。 (我必须做两次,因为完整的输出实际上并没有按照我需要的方式列出以秒为单位的持续时间。)

为避免大量重复代码,我想在一个函数中完成此操作。这是我的:

func ffprobeOperations() {
    var probeArguments = [String]()

    // get full ffprobe output to parse
    let probeArguments1 = [
        "-hide_banner",
        "\(inputFilePath)"]

    // get just file duration in seconds
    let probeArguments2 = [
        "-hide_banner",
        "-v",
        "0",
        "-show_entries",
        "format=duration",
        "-of",
        "compact=p=0:nk=1",
        "\(inputFilePath)"]

    var probePass: Int = 0
    if probePass == 1 {
        probeArguments = probeArguments2
    } else if probePass == 0 {
        probeArguments = probeArguments1
    }

    guard let launchPath = Bundle.main.path(forResource: "ffprobe", ofType: "") else { return }
    do {
        let probeTask: Process = Process()
        probeTask.launchPath = launchPath
        probeTask.arguments = probeArguments
        probeTask.standardInput = FileHandle.nullDevice
        let pipe = Pipe()
        probeTask.standardError = pipe
        probeTask.standardOutput = pipe
        let outHandle = pipe.fileHandleForReading
        outHandle.waitForDataInBackgroundAndNotify()

        var obs1 : NSObjectProtocol!
        obs1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable,
                                                                                                    object: outHandle, queue: nil) {  notification -> Void in
                                                                                                        let data = outHandle.availableData
                                                                                                        if data.count > 0 {
                                                                                                            if let str = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
                                                                                                                self.ffmpegLogOutput.string += ("\(str)")
                                                                                                                let range = NSRange(location:self.ffmpegLogOutput.string.count,length:0)
                                                                                                                self.ffmpegLogOutput.scrollRangeToVisible(range)
                                                                                                            }
                                                                                                            outHandle.waitForDataInBackgroundAndNotify()
                                                                                                        } else {
                                                                                                            print("EOF on stderr from process")
                                                                                                            NotificationCenter.default.removeObserver(obs1!)
                                                                                                        }
        }
        var obs2 : NSObjectProtocol!
        obs2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification,
                                                                                                    object: probeTask, queue: nil) { notification -> Void in
                                                                                                        print("terminated")
                                                                                                        NotificationCenter.default.removeObserver(obs2!)
        }
        probeTask.launch()
        probeTask.waitUntilExit()
        probePass += 1
    }
}

但无论我将 probePass += 1 放在函数的哪个位置,XCode 仍然会警告我条件 probePass == 1 永远不会为真,因此第二组通过永远不会执行参数。

我应该把 probePass += 1 放在哪里,或者有更好的方法来完成这个吗?

变量 probePass 的范围只是函数 ffProbeOptions,因为它是在其中创建的。这意味着一旦 ffProbeOptions 完成 运行,变量将被取消初始化。尝试在函数外定义 probePass,这样它的范围就更大了。这样变量就不会在你的函数每次完成时被销毁,它会跟踪它的值(例如 0 或 1)。

像这样:

var probePass = 0
func ffprobeOperations() {
    var probeArguments = [String]()

    // get full ffprobe output to parse
    let probeArguments1 = [
        "-hide_banner",
        "\(inputFilePath)"]

    // get just file duration in seconds
    let probeArguments2 = [
        "-hide_banner",
        "-v",
        "0",
        "-show_entries",
        "format=duration",
        "-of",
        "compact=p=0:nk=1",
        "\(inputFilePath)"]

    if probePass == 1 {
        probeArguments = probeArguments2
    } else if probePass == 0 {
        probeArguments = probeArguments1
    }

    guard let launchPath = Bundle.main.path(forResource: "ffprobe", ofType: "") else { return }
    do {
        let probeTask: Process = Process()
        probeTask.launchPath = launchPath
        probeTask.arguments = probeArguments
        probeTask.standardInput = FileHandle.nullDevice
        let pipe = Pipe()
        probeTask.standardError = pipe
        probeTask.standardOutput = pipe
        let outHandle = pipe.fileHandleForReading
        outHandle.waitForDataInBackgroundAndNotify()

        var obs1 : NSObjectProtocol!
        obs1 = NotificationCenter.default.addObserver(forName: NSNotification.Name.NSFileHandleDataAvailable,
                                                                                                    object: outHandle, queue: nil) {  notification -> Void in
                                                                                                        let data = outHandle.availableData
                                                                                                        if data.count > 0 {
                                                                                                            if let str = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
                                                                                                                self.ffmpegLogOutput.string += ("\(str)")
                                                                                                                let range = NSRange(location:self.ffmpegLogOutput.string.count,length:0)
                                                                                                                self.ffmpegLogOutput.scrollRangeToVisible(range)
                                                                                                            }
                                                                                                            outHandle.waitForDataInBackgroundAndNotify()
                                                                                                        } else {
                                                                                                            print("EOF on stderr from process")
                                                                                                            NotificationCenter.default.removeObserver(obs1!)
                                                                                                        }
        }
        var obs2 : NSObjectProtocol!
        obs2 = NotificationCenter.default.addObserver(forName: Process.didTerminateNotification,
                                                                                                    object: probeTask, queue: nil) { notification -> Void in
                                                                                                        print("terminated")
                                                                                                        NotificationCenter.default.removeObserver(obs2!)
        }
        probeTask.launch()
        probeTask.waitUntilExit()
        probePass += 1
    }
}

也许实现目标的更优雅的方法是定义一个 probeArguments 列表:

let probeArgumentList: [[String]] = [
    [   
        "-hide_banner",
        "\(inputFilePath)"
    ],
    [
        "-hide_banner",
        "-v",
        "0",
        "-show_entries",
        "format=duration",
        "-of",
        "compact=p=0:nk=1",
        "\(inputFilePath)"
    ]
]

然后遍历列表

for probeArguments in probeArgumentList {
    ## Perform operation
}