2016-09-16 3 views
0

Моя программа состоит из трех относительно разных областей: прослушивания сети для нового состояния, выполнения сетевых действий и обновления пользовательского интерфейса. Поэтому, соответственно, я хочу три класса: StateListener, ActionSender и ViewController, каждый из которых разбивается на отдельные потоки.Межпоточная связь между объектами в Swift 3 с Cocoa

Было бы так просто - троим нужно было взаимодействовать. Некоторые состояния, обнаруженные StateListener, требуют Действия, которые должны быть отправлены ActionSender или пользовательским интерфейсом, который будет обновляться с помощью ViewController. Некоторые ответы на действия требуют, чтобы пользовательский интерфейс обновлялся ViewController. Некоторые действия пользовательского интерфейса требуют действий, которые должен выполнять 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 для обновления представления после действия, но я попытался инициализировать ActionSender в ViewController.init, и я получил причудливые ошибки, связанные с Code.init, которые я не реализовал ...). Я хочу, чтобы получить выше ViewController и инициализирует все эти OperationQueues и объекты, где ViewController получает инициализированы, но я не могу найти, где это ...

Что я сделал выше, в основном объектно-ссылка инъекции каждого объект и OperationQueue. Я знаю, что есть другие способы сделать это (иерархия обратных вызовов, NSNotifications), но я не уверен, что это лучше всего.

Мой вопрос состоит из двух частей:

  1. Что является лучшим (то есть, быстрый, простой в реализации и обслуживании, наиболее идиоматических в Swift) способ получить между объектом и межпоточной связи Я желаю?

  2. В настоящее время я получаю информацию от функции ViewDontLLL ViewController, которая кажется ужасной (и означает, что я не могу получить «более высокую» перспективу ViewController. Куда это должно идти? AppDelegate рекламирует себя как «программу область стартапа», но я не могу получить доступ к ViewController оттуда ... XCode, кажется, скрытый запуск моего приложения от меня!

Я очень ценю ваши ответы!

+0

Это слишком расплывчато, слишком широко и, кажется, запрашивает мнения о «наилучшем способе» для достижения чего-либо, а на самом деле недостаточно информации для конкретных предложений. Это было сказано, что вы никогда не захотите так вращаться, ожидая какого-то «государственного» изменения. Вы хотите отвечать на события, а не блокировать поток в процессе. – Rob

+0

Re, делегат приложения, это то, где приложение запускается, и вместо делегирования приложения, получающего ссылку на контроллер вида, обычно это наоборот, когда контроллер представления может получить делегат приложения (например,'let appDelegate = NSApplication.shared(). делегировать как! AppDelegate' или 'let appDelegate = UIApplication.shared.delegate как! AppDelegate') и тем самым получить ссылки на объекты, которыми может управлять делегат приложения. – Rob

+0

Роб: спасибо за ваш комментарий. Я старался быть таким же конкретным, как я мог бы быть без грязных вод, но, очевидно, я не смог дать достаточно подробностей. Сожалею! Что касается неприязни к ожиданию того, что какое-то государство изменится, какова альтернатива? Если вы отвечаете на события, вы обязательно должны слушать события? Я должен уточнить, что waitForNewState() возвращает только когда новое состояние было нажато моим сервером. И государства будут густыми и быстрыми, поэтому значительная часть времени будет иметь дело с ними. – SuddenMoustache

ответ

0

Этот пост значительно помогли с вопросом 2 и проблемой передачи себя как параметра члену данных в инициализаторе: 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() 
    } 
} 
Смежные вопросы