Skip to content

Instantly share code, notes, and snippets.

@ryanashcraft
Created January 19, 2020 22:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanashcraft/bca678bf61ac427675b730cd0054806f to your computer and use it in GitHub Desktop.
Save ryanashcraft/bca678bf61ac427675b730cd0054806f to your computer and use it in GitHub Desktop.
RemoteInspector.swift
import Foundation
public class RemoteInspector {
private struct UpdateMessage<T: Encodable>: Encodable {
let type = "update"
var id: String
var data: T
}
private struct LogMessage: Encodable {
let type = "log"
var message: String
var level: String
var attributesJSON: String?
}
public static let shared = RemoteInspector()
static func connect(url: URL) -> URLSessionWebSocketTask {
let urlSession = URLSession(configuration: .default)
return urlSession.webSocketTask(with: url)
}
var webSocketTask: URLSessionWebSocketTask?
var url: URL?
public var isConnected: Bool {
return webSocketTask?.state == .running
}
public func connect(url: URL) -> Bool {
#if !DEBUG
return false
#else
self.url = url
webSocketTask = Self.connect(url: url)
if let webSocketTask = webSocketTask {
logger.infoMessage("Starting remote inspector session at \(url.absoluteString)")
webSocketTask.resume()
return true
}
return false
#endif
}
func reconnect() -> Bool {
guard let webSocketTask = webSocketTask else {
return false
}
webSocketTask.cancel(with: .goingAway, reason: nil)
if let url = url {
return connect(url: url)
}
return false
}
public func disconnect() {
guard let webSocketTask = webSocketTask else {
return
}
webSocketTask.cancel(with: .goingAway, reason: nil)
self.webSocketTask = nil
}
public func send(_ id: String, _ value: Encodable) {
guard let webSocketTask = webSocketTask else {
return
}
do {
let encoder = JSONEncoder()
let jsonData = try encoder.encode(UpdateMessage(id: id, data: AnyEncodable(value: value)))
let message = URLSessionWebSocketTask.Message.data(jsonData)
webSocketTask.send(message) { error in
if let error = error {
_ = self.reconnect()
logger.errorMessage("\(error)")
}
}
} catch {
// Blegh
}
}
func log(_ message: String, logLevel: String, attributes: [String: Any]? = nil) {
guard let webSocketTask = webSocketTask else {
return
}
let encoder = JSONEncoder()
var attributesJSON: Data?
if let attributes = attributes {
attributesJSON = try? JSONSerialization.data(withJSONObject: attributes, options: [])
}
guard let jsonData: Data = {
do {
if let attributesJSON = attributesJSON {
return try encoder.encode(
LogMessage(
message: message,
level: logLevel.description,
attributesJSON: String(data: attributesJSON, encoding: .utf8)
)
)
} else {
return try encoder.encode(
LogMessage(
message: message,
level: logLevel.description,
attributesJSON: nil
)
)
}
} catch {
return nil
}
}() else {
return
}
let message = URLSessionWebSocketTask.Message.data(jsonData)
webSocketTask.send(message) { error in
if let error = error {
_ = self.reconnect()
logger.errorMessage("\(error)")
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment