试图在swift

时间:2016-02-16 10:43:03

标签: ios xcode swift publish-subscribe

我实际上是想在我的Swift项目中实现一个pub / sub模式,我有很少的 Agents Singleton s)执行任务,当他们的状态发生变化时他们应该通知所有听众以前订阅的。

我得到了修改我的协议的错误,可能它应该符合Equatable协议,但我看不出以哪种方式(声明protocol AvailableChatListener: Equatable无法解析)。

我知道我可以使用Apple的NSNotificationCenter(好点here),但这不是一个完全符合我要求的解决方案。

这里是代码:

AvailableChatListener.swift

protocol AvailableChatListener {
    func onAvailableChatChange()
}

AvailableChatAgent.swift

class AvailableChatAgent {
  // MARK: - Singleton

  class var sharedInstance: AvailableChatAgent {
    struct Singleton {
      static let instance = AvailableChatAgent()
    }
    return Singleton.instance
  }

  // MARK: - Listeners

  private var availableChatListeners = [AvailableChatListener]()

  // MARK: - Public Properties

  // current Chats
  var currentChats = [Chat]()   {
    didSet  {
      statusChanged()
    }
  }

  func startObserving()   {
    // ...
    // perform tasks and change currentChats
    // ...
  }

  func stopObserving()    {
    // ...
    // stop tasks
    // ...
  }

  func statusChanged()    {

    // notify listeners
    for receiver in availableChatListeners {
      receiver.onAvailableChatChange()
    }
  }

  // ERROR #1
  func subscribeListener(listener: AvailableChatListener)    {
    availableChatListeners.append(listener)
  }

  // ERROR #1
  func unsubscribeListener(listener: AvailableChatListener)  {

    // ERROR #2
    if let index = availableChatListeners.indexOf(listener) {
      availableChatListeners.removeAtIndex(availableChatListeners.indexOf(listener)!)

      if availableChatListeners.count == 0 {
        self.stopObserving()
      }
    }
  }
}

在这里我使用这个逻辑(例如在TableViewController中)

ChatListTableViewController.swift

class ChatListTableViewController: UITableViewController, AvailableChatListener {

  // MARK: - Properties

  var availableChatAgent = AvailableChatAgent.sharedInstance

  // MARK: - ViewDidLoad

  override func viewDidLoad() {
    super.viewDidLoad()

    availableChatAgent.subscribeListener(self)
  }

  // MARK: - Implement AvailableChatListener

  func onAvailableChatChange()    {
    // perform task with the new data, for example update UI
  }
}

提前致谢。

更新1

我得到的错误:

  1. protocol "AvailableChatListener' can only be used as a generic constraint because it has Self or associated type requirements
  2. Cannot convert value of type 'AvailableChatListener' to expect argument type '@noescpae(AvailableChatListener) throws -> Bool'

2 个答案:

答案 0 :(得分:0)

请尝试删除侦听器的方法,看看它是否有效。我已将对象转换为NSArray,然后在该数组中查找侦听器的索引。我假设两个听众是相同的,如果他们是同一个对象,而不是任何其他条件。

func unsubscribeListener(listener: AvailableChatListener)  {
    let arr = availableChatListeners as NSArray
    let index = arr.indexOfObject(listener)
    if index != NSNotFound {
        availableChatListeners.removeAtIndex(index)
        if availableChatListeners.count == 0 {
            self.stopObserving()
        }
    }
}

您还应该以这种方式声明您的协议(添加@objc)

@objc protocol AvailableChatListener  {
    func onAvailableChatChange()
}

答案 1 :(得分:0)

我遇到了同样的问题并做了以下事情来解决它。 Objective-C Sets的使用需要使用基于NSObject的订阅者来克服所提到的Hashing问题。

import UIKit

protocol LogoListener {
    func logo(urlString url: String, hasImage image: UIImage)
}

class Server {
    var logoListeners = NSMutableSet()
    func addListener(listener: LogoListener) {
        logoListeners.add(listener)
        print("Added listener \(listener)")
    }
}

class Registration: NSObject, LogoListener {
    func logo(urlString url: String, hasImage image: UIImage) {
        savedImage = image
    }
    var savedImage: UIImage = UIImage()
    override init() {
        super.init()
        let server = Server()
        server.addListener(listener: self)
    }
}

let reg = Registration()