使用 NSURLSession 在 Swift 上编写的 SSE 客户端。
这是一个使用 Swift 编写的 EventSource 实现,遵循 W3C EventSource 文档。如果缺少某些内容或不完全正确,请提出 issue,我会处理它!
如果您喜欢这个库,请给我们一个 ★。这有助于我们保持对维护的参与!
我花了一些时间审查了 github 上所有 fork、pull request 和 issue。我发现的主要变化和抱怨与连接和 Last-Event-Id
处理有关。
此版本中的更改是
EventSource
不再自动连接。它会等到调用 connect(lastEventId: String? = nil)
方法。此方法接受一个 lastEventId
,该 lastEventId
将在连接时发送到服务器。EventSource
允许您随时调用 disconnect()
。EventSource
不再存储 Last-Event-Id
,您必须负责存储 id
并在 connect
方法中使用或不使用它发送。EventSource
根本不会重新连接。如果发生网络层错误(断开连接、超时等)或者服务器关闭连接,您将需要负责与服务器重新连接。Swift 1.0
开始就已经存在,最初只是作为学习该语言的一种方式。在这个新版本中,整个代码都得到了改进、注释和充分的测试,以便更容易地跟踪问题并在将来扩展。在存储库中有一个简单的工作示例。查看 ViewController.swift 以了解如何使用它。
同样,在 sse-server
文件夹中,您会找到一个非常简单的 node.js
服务器来测试该库。要运行服务器,您只需要
npm install
node sse.js
在您的 Podfile
中包含 EventSource: pod 'IKEventSource'
导入框架
import IKEventSource
在您的 Cartfile
中包含 EventSource:github "inaka/EventSource"
导入框架
import IKEventSource
有关更多参考,请参见 Carthage 的文档。
Package.swift
中包含 EventSource:github "inaka/EventSource"
import PackageDescription
let package = Package(
dependencies: [
.package(url: "https://github.com/inaka/EventSource.git", .branch("master"))
])
import IKEventSource
/// RetryTime: This can be changed remotly if the server sends an event `retry:`
var retryTime: Int { get }
/// URL where EventSource will listen for events.
var url: URL { get }
/// The last event id received from server. This id is neccesary to keep track of the last event-id received to avoid
/// receiving duplicate events after a reconnection.
var lastEventId: String? { get }
/// Current state of EventSource
var readyState: EventSourceState { get }
/// Method used to connect to server. It can receive an optional lastEventId indicating the Last-Event-ID
///
/// - Parameter lastEventId: optional value that is going to be added on the request header to server.
func connect(lastEventId: String?)
/// Method used to disconnect from server.
func disconnect()
/// Returns the list of event names that we are currently listening for.
///
/// - Returns: List of event names.
func events() -> [String]
/// Callback called when EventSource has successfully connected to the server.
///
/// - Parameter onOpenCallback: callback
func onOpen(_ onOpenCallback: @escaping (() -> Void))
/// Callback called once EventSource has disconnected from server. This can happen for multiple reasons.
/// The server could have requested the disconnection or maybe a network layer error, wrong URL or any other
/// error. The callback receives as parameters the status code of the disconnection, if we should reconnect or not
/// following event source rules and finally the network layer error if any. All this information is more than
/// enought for you to take a decition if you should reconnect or not.
/// - Parameter onOpenCallback: callback
func onComplete(_ onComplete: @escaping ((Int?, Bool?, NSError?) -> Void))
/// This callback is called everytime an event with name "message" or no name is received.
func onMessage(_ onMessageCallback: @escaping ((_ id: String?, _ event: String?, _ data: String?) -> Void))
/// Add an event handler for an specific event name.
///
/// - Parameters:
/// - event: name of the event to receive
/// - handler: this handler will be called everytime an event is received with this event-name
func addEventListener(_ event: String,
handler: @escaping ((_ id: String?, _ event: String?, _ data: String?) -> Void))
/// Remove an event handler for the event-name
///
/// - Parameter event: name of the listener to be remove from event source.
func removeEventListener(_ event: String)
事件:
id: event-id
event: event-name
data: event-data
调用
eventSource.addEventListener("event-name") { (id, event, data) in
// Here you get an event 'event-name'
}
事件:
id: event-id
data: event-data
data: event-data
调用
eventSource.onMessage { (id, event, data) in
// Here you get an event without event name!
}
事件:
id: event-id
data: event-data-1
data: event-data-2
data: event-data-3
调用
eventSource.onMessage { (id, event, data) in
// Here you get an event without event name!
// data: event-data-1\nevent-data-2\nevent-data-3
}
事件:
:heartbeat
调用
nothing it's a comment
这是应用程序附带的示例。如果您运行服务器并运行应用程序,您将能够看到此示例的直播。移动的盒子只是为了表明一切都在后台工作,并且主线程性能没有下降。(gif 看起来很糟糕,但是如果您单击图像,您将被带到 gfycat 版本的 gif,它运行得更流畅)
感谢所有贡献者指出缺失的东西或问题并修复它们或提出问题!!
如果您在使用此库时发现任何 bug 或有 问题,请在此 repo 中提出 issue(或 pull request :))。
请提供您遇到的问题的示例。如果事件未正确解析,请提供示例事件。