1
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,73 @@
|
||||
import Foundation
|
||||
|
||||
class SSEClient: NSObject {
|
||||
private var url: URL
|
||||
private var headers: [String: String]
|
||||
private var eventSourceTask: URLSessionDataTask?
|
||||
private var onMessageCallback: ((String) -> Void)?
|
||||
private var onOpenCallback: (() -> Void)?
|
||||
private var onErrorCallback: ((Error?) -> Void)?
|
||||
|
||||
init(url: URL, headers: [String: String] = [:]) {
|
||||
self.url = url
|
||||
self.headers = headers
|
||||
super.init()
|
||||
}
|
||||
|
||||
func onMessage(_ callback: @escaping (String) -> Void) {
|
||||
onMessageCallback = callback
|
||||
}
|
||||
|
||||
func onOpen(_ callback: @escaping () -> Void) {
|
||||
onOpenCallback = callback
|
||||
}
|
||||
|
||||
func onError(_ callback: @escaping (Error?) -> Void) {
|
||||
onErrorCallback = callback
|
||||
}
|
||||
|
||||
func start() {
|
||||
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
// 添加默认的SSE头信息
|
||||
request.addValue("text/event-stream", forHTTPHeaderField: "Accept")
|
||||
request.addValue("no-cache", forHTTPHeaderField: "Cache-Control")
|
||||
|
||||
// 添加自定义头信息
|
||||
for (key, value) in headers {
|
||||
request.addValue(value, forHTTPHeaderField: key)
|
||||
}
|
||||
|
||||
eventSourceTask = session.dataTask(with: request)
|
||||
eventSourceTask?.resume()
|
||||
}
|
||||
|
||||
func stop() {
|
||||
eventSourceTask?.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
extension SSEClient: URLSessionDataDelegate {
|
||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
guard let string = String(data: data, encoding: .utf8) else { return }
|
||||
let lines = string.components(separatedBy: .newlines)
|
||||
|
||||
for line in lines {
|
||||
if line.isEmpty { continue }
|
||||
if line.hasPrefix("data: ") {
|
||||
let message = line.replacingOccurrences(of: "data: ", with: "")
|
||||
onMessageCallback?(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||
completionHandler(.allow)
|
||||
onOpenCallback?()
|
||||
}
|
||||
|
||||
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
onErrorCallback?(error)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"deploymentTarget": "12"
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import { URL } from 'Foundation';
|
||||
import { Dictionary } from "Swift";
|
||||
import {xSSEOptions} from "../interface.uts"
|
||||
|
||||
|
||||
export class SSEClientApp {
|
||||
private sseClient : SSEClient
|
||||
public url : string = ''
|
||||
private closed:boolean = true;
|
||||
private onOpenEvt = () => { }
|
||||
private onErrorEvt = () => { }
|
||||
private onClosedEvt = () => { }
|
||||
private onMessageEvt = (data : string) => { }
|
||||
|
||||
|
||||
constructor(options:xSSEOptions) {
|
||||
this.url = options.url;
|
||||
let _headers = new Map<string, string>()
|
||||
const headersOpts = (options.header!=null?(options.header as UTSJSONObject):({} as UTSJSONObject))
|
||||
for(const key in headersOpts){
|
||||
_headers.set(key,headersOpts.getString(key)!)
|
||||
}
|
||||
|
||||
this.sseClient = new SSEClient(url = new URL(string = this.url)!, headers = _headers)
|
||||
|
||||
}
|
||||
@UTSJS.keepAlive
|
||||
onOpen(callback:()=>void){
|
||||
this.onOpenEvt = callback
|
||||
}
|
||||
@UTSJS.keepAlive
|
||||
onError(callback:()=>void){
|
||||
this.onErrorEvt = callback
|
||||
}
|
||||
@UTSJS.keepAlive
|
||||
onClosed(callback:()=>void){
|
||||
this.onClosedEvt = callback
|
||||
}
|
||||
@UTSJS.keepAlive
|
||||
onMessage(callback:(data:string)=>void){
|
||||
this.onMessageEvt = callback
|
||||
}
|
||||
|
||||
connect(headers:UTSJSONObject = {}) {
|
||||
let _headers = new Map<string, string>()
|
||||
for(const key in headers){
|
||||
_headers.set(key,headers.getString(key)!)
|
||||
}
|
||||
console.log(_headers.size)
|
||||
if(!this.closed) return;
|
||||
this.sseClient = new SSEClient(url = new URL(string = this.url)!, headers = _headers)
|
||||
this.closed = true;
|
||||
this.sseClient.start()
|
||||
let _this = this;
|
||||
this.sseClient.onMessage((data:string)=>{
|
||||
_this.onMessageEvt(data)
|
||||
})
|
||||
this.sseClient.onOpen(()=>{
|
||||
_this.onOpenEvt()
|
||||
_this.closed = false;
|
||||
})
|
||||
this.sseClient.onError((error:any|null)=>{
|
||||
_this.onErrorEvt()
|
||||
console.error(error)
|
||||
_this.closed = true;
|
||||
})
|
||||
}
|
||||
disconnect() {
|
||||
this.sseClient.stop()
|
||||
this.closed = true;
|
||||
this.onClosedEvt()
|
||||
}
|
||||
isConnected() : boolean {
|
||||
return !this.closed;
|
||||
}
|
||||
}
|
||||
/**
|
||||
// 在 ViewController 中使用
|
||||
class ViewController: UIViewController {
|
||||
private var sseClient: SSEClient?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// 初始化 SSE 客户端
|
||||
if let url = URL(string: "https://your-sse-server.com/events") {
|
||||
sseClient = SSEClient(url: url)
|
||||
sseClient?.delegate = self
|
||||
sseClient?.connect()
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
sseClient?.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
// 实现代理方法
|
||||
extension ViewController: SSEClient.EventSourceDelegate {
|
||||
func eventSourceDidOpen() {
|
||||
print("SSE 连接已打开")
|
||||
}
|
||||
|
||||
func eventSourceDidReceiveMessage(event: String?, data: String) {
|
||||
print("收到消息: event=\(event ?? ""), data=\(data)")
|
||||
}
|
||||
|
||||
func eventSourceDidError(_ error: Error) {
|
||||
print("发生错误: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
func eventSourceDidClose() {
|
||||
print("连接已关闭")
|
||||
}
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user