diff --git a/README.md b/README.md
index 438270f..cdedda8 100644
--- a/README.md
+++ b/README.md
@@ -16,11 +16,13 @@ To install, simply:
#### Swift Package Manager
+#### ⚠️ For iOS before 13 version, please use 0.4.0
+
Add the following line to your `Package.swift`
```swift
// ...
- .package(name: "ActionCableSwift", url: "https://github.com/nerzh/Action-Cable-Swift.git", from: "0.3.2"),
+ .package(name: "ActionCableSwift", url: "https://github.com/nerzh/Action-Cable-Swift.git", from: "1.0.0"),
targets: [
.target(
name: "YourPackageName",
@@ -30,301 +32,14 @@ Add the following line to your `Package.swift`
// ...
```
-#### Cocoa Pods
-
-Add the following line to your `Podfile`
-
-```ruby
- pod 'ActionCableSwift'
-```
-
-and you can import ActionCableSwift
-
-```swift
- import ActionCableSwift
-```
# Usage
----
-
-## Your WebSocketService should to implement the `ACWebSocketProtocol` protocol.
-
----
-
-### Use with [Websocket-kit](https://github.com/vapor/websocket-kit)
-
-#### I highly recommend not using Starscream to implement a WebSocket, because they have a strange implementation that does not allow conveniently reconnecting to a remote server after disconnecting. There is also a cool and fast alternative from the [Swift Server Work Group (SSWG)](https://swift.org/server/), package named [Websocket-kit](https://github.com/vapor/websocket-kit).
-
-[Websocket-kit](https://github.com/vapor/websocket-kit) is SPM(Swift Package Manager) client library built on [Swift-NIO](https://github.com/apple/swift-nio)
-
-Package.swift
-```swift
- // ...
- dependencies: [
- .package(name: "ActionCableSwift", url: "https://github.com/nerzh/Action-Cable-Swift.git", from: "0.3.0"),
- .package(name: "websocket-kit", url: "https://github.com/vapor/websocket-kit.git", .upToNextMinor(from: "2.0.0"))
- ],
- targets: [
- .target(
- name: "YourPackageName",
- dependencies: [
- .product(name: "ActionCableSwift", package: "ActionCableSwift"),
- .product(name: "WebSocketKit", package: "websocket-kit")
- ])
- // ...
-```
-
-
-or inside xcode
-
-
-
-
-
-
- SPOILER: Recommended implementation WSS based on Websocket-kit(Swift-NIO)
-
-
- This is propertyWrapper for threadsafe access to webSocket instance
-
- ```swift
- import Foundation
-
- @propertyWrapper
- struct Atomic {
-
- private var value: Value
- private let lock = NSLock()
-
- init(wrappedValue value: Value) {
- self.value = value
- }
-
- var wrappedValue: Value {
- get { return load() }
- set { store(newValue: newValue) }
- }
-
- func load() -> Value {
- lock.lock()
- defer { lock.unlock() }
- return value
- }
-
- mutating func store(newValue: Value) {
- lock.lock()
- defer { lock.unlock() }
- value = newValue
- }
- }
-
- ```
-
-This is implementation WSS
-
- ```swift
-import NIO
-import NIOHTTP1
-import NIOWebSocket
-import WebSocketKit
-
-final class WSS: ACWebSocketProtocol {
-
- var url: URL
- private var eventLoopGroup: EventLoopGroup
- @Atomic var ws: WebSocket?
-
- init(stringURL: String, coreCount: Int = System.coreCount) {
- url = URL(string: stringURL)!
- eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: coreCount)
- }
-
- var onConnected: ((_ headers: [String : String]?) -> Void)?
- var onDisconnected: ((_ reason: String?) -> Void)?
- var onCancelled: (() -> Void)?
- var onText: ((_ text: String) -> Void)?
- var onBinary: ((_ data: Data) -> Void)?
- var onPing: (() -> Void)?
- var onPong: (() -> Void)?
-
- func connect(headers: [String : String]?) {
-
- var httpHeaders: HTTPHeaders = .init()
- headers?.forEach({ (name, value) in
- httpHeaders.add(name: name, value: value)
- })
- let promise: EventLoopPromise = eventLoopGroup.next().makePromise(of: Void.self)
-
- WebSocket.connect(to: url.absoluteString,
- headers: httpHeaders,
- on: eventLoopGroup
- ) { ws in
- self.ws = ws
-
- ws.onPing { [weak self] (ws) in
- self?.onPing?()
- }
-
- ws.onPong { [weak self] (ws) in
- self?.onPong?()
- }
-
- ws.onClose.whenComplete { [weak self] (result) in
- switch result {
- case .success:
- self?.onDisconnected?(nil)
- self?.onCancelled?()
- case let .failure(error):
- self?.onDisconnected?(error.localizedDescription)
- self?.onCancelled?()
- }
- }
-
- ws.onText { (ws, text) in
- self.onText?(text)
- }
-
- ws.onBinary { (ws, buffer) in
- var data: Data = Data()
- data.append(contentsOf: buffer.readableBytesView)
- self.onBinary?(data)
- }
-
- }.cascade(to: promise)
-
- promise.futureResult.whenSuccess { [weak self] (_) in
- guard let self = self else { return }
- self.onConnected?(nil)
- }
- }
-
- func disconnect() {
- ws?.close(promise: nil)
- }
-
- func send(data: Data) {
- ws?.send([UInt8](data))
- }
-
- func send(data: Data, _ completion: (() -> Void)?) {
- let promise: EventLoopPromise? = ws?.eventLoop.next().makePromise(of: Void.self)
- ws?.send([UInt8](data), promise: promise)
- promise?.futureResult.whenComplete { (_) in
- completion?()
- }
- }
-
- func send(text: String) {
- ws?.send(text)
- }
-
- func send(text: String, _ completion: (() -> Void)?) {
- let promise: EventLoopPromise? = ws?.eventLoop.next().makePromise(of: Void.self)
- ws?.send(text, promise: promise)
- promise?.futureResult.whenComplete { (_) in
- completion?()
- }
- }
-}
- ```
-
-
----
-
-### Use with [Starscream](https://github.com/daltoniam/Starscream)
-
-```ruby
- pod 'Starscream', '~> 4.0.0'
-```
-
- SPOILER: If you still want to use "Starscream", then you can to copy this code for websocket client
-
-```swift
-import Foundation
-import Starscream
-
-class WSS: ACWebSocketProtocol, WebSocketDelegate {
-
- var url: URL
- var ws: WebSocket
-
- init(stringURL: String) {
- url = URL(string: stringURL)!
- ws = WebSocket(request: URLRequest(url: url))
- ws.delegate = self
- }
-
- var onConnected: ((_ headers: [String : String]?) -> Void)?
- var onDisconnected: ((_ reason: String?) -> Void)?
- var onCancelled: (() -> Void)?
- var onText: ((_ text: String) -> Void)?
- var onBinary: ((_ data: Data) -> Void)?
- var onPing: (() -> Void)?
- var onPong: (() -> Void)?
-
- func connect(headers: [String : String]?) {
- ws.request.allHTTPHeaderFields = headers
- ws.connect()
- }
-
- func disconnect() {
- ws.disconnect()
- }
-
- func send(data: Data) {
- ws.write(data: data)
- }
-
- func send(data: Data, _ completion: (() -> Void)?) {
- ws.write(data: data, completion: completion)
- }
-
- func send(text: String) {
- ws.write(string: text)
- }
-
- func send(text: String, _ completion: (() -> Void)?) {
- ws.write(string: text, completion: completion)
- }
-
- func didReceive(event: WebSocketEvent, client: WebSocket) {
- switch event {
- case .connected(let headers):
- onConnected?(headers)
- case .disconnected(let reason, let code):
- onDisconnected?(reason)
- case .text(let string):
- onText?(string)
- case .binary(let data):
- onBinary?(data)
- case .ping(_):
- onPing?()
- case .pong(_):
- onPong?()
- case .cancelled:
- onCancelled?()
- default: break
- }
- }
-}
-
-```
-
-
----
-
-### Next step to use ActionCableSwift
-
-
```swift
import ActionCableSwift
-/// web socket client
-let ws: WSS = .init(stringURL: "ws://localhost:3001/cable")
-
/// action cable client
let clientOptions: ACClientOptions = .init(debug: false, reconnect: true)
-let client: ACClient = .init(ws: ws, options: clientOptions)
+let client: ACClient = .init(stringURL: "ws://localhost:3001/cable", options: clientOptions)
/// pass headers to connect
/// on server you can get this with env['HTTP_COOKIE']
client.headers = ["COOKIE": "Value"]
@@ -402,13 +117,23 @@ client.headers = [
---
-## Requirements
+# If you want to implement your own WebSocket Provider, you should to implement the `ACWebSocketProtocol` protocol and use another initializator for ACClient
-Any Web Socket Library, e.g.
+```swift
+import ActionCableSwift
-[Websocket-kit](https://github.com/vapor/websocket-kit)
+/// web socket client
+let ws: YourWSS = .init(stringURL: "ws://localhost:3001/cable")
+
+/// action cable client
+let clientOptions: ACClientOptions = .init(debug: false, reconnect: true)
+let client: ACClient = .init(ws: ws, options: clientOptions)
+```
-[Starscream](https://github.com/daltoniam/Starscream)
+---
+## Requirements
+
+[Websocket-kit](https://github.com/vapor/websocket-kit)
## Author