swift - Swift 3 中与 Cocoa 的线程间对象通信

标签 swift cocoa concurrency viewcontroller swift3

我的程序由三个相对不同的区域组成:在网络上监听新状态、执行网络操作以及更新 UI。因此,我分别需要三个类:StateListener、ActionSender 和 ViewController,每个类都在单独的线程上运行。

事情有这么简单就好了——三者需要互动。 StateListener 发现的某些状态需要 ActionSender 发送 Actions 或 ViewController 更新 UI。某些对 Actions 的响应需要 ViewController 更新 UI。某些 UI 操作需要由 ActionSender 执行操作。

目前我做了这样的事情(伪代码):

/* ViewController.swift */
class ViewController : blah
{
    //...
    func buttonPressed()
    {
        // ?! Need to do an action here but I can't 
        // because actionSender is initialised below...
    }

    func viewDidLoad()
    {
        let actionSender = ActionSender(m_view: self)
        let actionQueue = OperationQueue()
        let stateListener = StateListener(m_view: self, 
                                          m_actionSender: actionSender,                    
                                          m_actionQueue: actionQueue)
        let stateQueue = OperationQueue()
        stateQueue.addOperation(stateQueue.listen())
    }
}

/* StateListener.swift */
class StateListener
{
    // ...
    func listen()
    {
        while true
        {
            var state = waitForNewState()
            if shouldActOn(state)
            {
                m_actionQueue.addOperation(m_actionSender.act())
            }
        }
    }
}

/* ActionSender.swift */
class ActionSender
{
    // ...
    func act()
    {
        var reply = sendAction()
        OperationQueue.main.addOperation(m_view.m_textBox.append(reply))
    }
}

这相本地狱般,甚至没有做我想要它做的事情,因为我无法让 ViewController 执行操作(ActionSender 需要 ViewController 引用来在操作后更新 View ,但我尝试初始化 ActionSender在 ViewController.init 中,我遇到了与我没有实现的 Code.init 有关的奇怪错误...)。我想要到达 ViewController 上方并在 ViewController 初始化的任何地方初始化所有这些操作队列和对象,但我找不到它在哪里......

我上面所做的基本上是每个对象和OperationQueue的对象引用注入(inject)。我知道还有其他方法可以做到这一点(回调层次结构、NSNotifications),但我不确定哪种方法最好。

我的问题分为两部分:

  1. 获得我想要的对象间和线程间通信的最佳(即最快、最容易实现和维护、Swift 中最惯用的)方法是什么?

  2. 我目前从 ViewController 的 viewDidLoad 函数中获取信息,这看起来很糟糕(并且意味着我无法获得 ViewController 的“更高层”视角。这些东西应该去哪里?AppDelegate 将自己宣传为“程序启动区域,但我无法从那里访问 ViewController...XCode 似乎对我隐藏了我的应用程序的启动!

非常感谢您的回复!

最佳答案

这篇文章极大地帮助了问题 2 以及将 self 作为参数传递给初始化程序中的数据成员的问题:http://blog.scottlogic.com/2014/11/20/swift-initialisation.html

具体来说,我可以使用这种模式:

class Foo : blah
{
    var m_bar : Bar!

    init() {
        // notice I get away with not initialising m_bar
    }

    func viewDidLoad {
        m_bar = Bar(m_foo: self)
        m_bar.doYourThing()
    }
}

该博客更喜欢以下内容,出于对作者的感谢,我觉得我应该在此处添加这些内容,尽管我更喜欢上面的内容。

class Foo : blah
{
    lazy var m_bar : Bar = {
        return Bar(m_foo: self)  // notice I can pass in self
    }

    init() {
        // notice I get away with not initialising m_bar
    }

    func viewDidLoad {
        m_bar.doYourThing()
    }
}

关于swift - Swift 3 中与 Cocoa 的线程间对象通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39537949/

相关文章:

cocoa - 如何使用 URL 开始调试 Cocoa 应用程序?

java - 我可以在 Oracle 中进行原子 MERGE 吗?

unit-testing - 在 go 中测试连接的正确方法

go - channel 并发问题

ios - 无法使用 Swift 上的多部分请求将图像上传到 Paperclip

swift - Snapkit:将倍数限制为边距

swift - 如何为 NSButtonCell 指定 alpha? (对于禁用状态)

swift - 创建带参数的枚举

ios - 导航到新的 UINavigationController

cocoa - 在一个类的 2 个自定义 View 中分别绘制