【问题标题】:How to return NSLog output in real time as a class property in Swift如何在 Swift 中将 NSLog 输出作为类属性实时返回
【发布时间】:2016-06-29 00:03:51
【问题描述】:

我在 Swift 中有两个类,一个是 ViewController.swift,另一个有一些业务逻辑,叫做 Brain.swift。在 Brain.swift 中,我有一个类,其中包含一个名为 convert() 的函数,它执行一个 NSTask。

在 ViewController.swift 中发生所有 UI 更新。

我想要完成的是将 convert() 的 NSTask 的输出转换为 ViewController 中的 TextView。

我已经实现了this answer 的解决方案,但我有点新手,所以我不确定如何将其作为类属性实时返回以供其他类访问。​​

Brain.swift

import Foundation


internal func convert(chosenFile: NSURL, addText: (newText: String) -> Void) {


    let bundle = NSBundle.mainBundle()

    let task = NSTask()

    let outputPipe = NSPipe()

    task.standardOutput = outputPipe
    let outHandle = outputPipe.fileHandleForReading

    outHandle.readabilityHandler = { outputPipe in
        if let line = String(data: outputPipe.availableData, encoding: NSUTF8StringEncoding) {
            addText(newText: line)
        } else {
            print("Error decoding data: \(outputPipe.availableData)")
        }
    }

    task.launch()
    task.waitUntilExit()

}

ViewController.swift

    @IBAction func Run(sender: AnyObject) {

    let qualityOfServiceClass = QOS_CLASS_USER_INITIATED
    let userInitiatedQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
    dispatch_async(userInitiatedQueue, {
        self.btnConvert.enabled = false
        self.btnSelect.enabled = false
        self.activitySpinner.hidden = false
        self.activitySpinner.startAnimation(self)


        convert(self.inputFile.chosenFile) { newText in
                self.statusText.stringValue = "\(newText)"
        }
    })

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.statusText.stringValue = "Done!"
        self.activitySpinner.hidden = true
        self.activitySpinner.stopAnimation(self)

        self.btnSelect.enabled = true

    })
}

【问题讨论】:

    标签: ios swift macos nstask


    【解决方案1】:

    这应该可行:

    func convert(chosenFile: NSURL, addText: (newText: String) -> Void) {
        let task = NSTask()
    
        // Set up task
    
        let pipe = NSPipe()
        task.standardOutput = pipe
        let outHandle = pipe.fileHandleForReading
    
        outHandle.readabilityHandler = { pipe in
            if let line = String(data: pipe.availableData, encoding: NSUTF8StringEncoding) {
                addText(newText: line)
            } else {
                print("Error decoding data: \(pipe.availableData)")
            }
        }
    
        task.launch()
    }
    

    你可以这样称呼它:

    convert(myURL) { newText in
        print("New output available: \(newText)")
    }
    

    我从你的类中创建了一个函数,因为当你只想将它用于单个函数时,没有理由创建一个类。 readabilityHandler 方法也大大简化了您的代码。

    我还添加了这种获取上述问题更新的方式。

    【讨论】:

    • 谢谢,但我无法使用此解决方案检索文本。我已经将类变成了一个函数,但似乎 convert() { } 函数调用中的任何内容都没有被执行。我用调试器检查了这个。是否需要与 GCD 进行多线程? readabilityHandler 已经是多线程的了吗?
    • @user43633 如果它没有被执行,你没有调用它,再次检查或显示相关代码。是的,readabilityHandler 已经在单独的线程上调用了。请注意,此函数不会等到任务完成,而是使用提供的闭包在发生某些事情时向您提供反馈。
    • 感谢您确认关于 readabiltyHandler,我已经更新了相关代码。我认为我的线程实现可能不正确,这导致了我的问题,可能与您的解决方案无关。
    • @user43633 您应该使用主线程对 UI 进行更新(将标签文本分配给 newText)。您可能还想添加文本而不是覆盖整个标签。确保您的函数实际上也被调用。还要确保将您的NSTask 设置为您要执行的任务。初始化一个 NSTask 而不告诉它要做什么,你最终会得到一个什么都不做的任务。
    猜你喜欢
    • 2012-02-17
    • 2020-03-26
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2012-05-31
    • 2010-10-13
    • 2022-01-22
    相关资源
    最近更新 更多