我实际上是想在我的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
我得到的错误:
protocol "AvailableChatListener' can only be used as a generic constraint because it has Self or associated type requirements
Cannot convert value of type 'AvailableChatListener' to expect argument type '@noescpae(AvailableChatListener) throws -> Bool'
答案 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()