URLSessionWebSocketTask - boostcampwm2023/iOS05-Village GitHub Wiki
์ด์ ๋ด์ฉ
- ์ค์ํํธ์์ ์ ๊ณตํ๋ URLSessionWebsocketTask์ ๋ํด์ ํ์ต
์ ํ ์ฌํญ
- ๊ธฐ์กด์ ๋ง์ด ์ฌ์ฉ๋์๋ ์ธ๋ถ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ [socket.io](http://socket.io) starstream ๋ณด๋ค
- ์ ํ์์ ์ ๊ณตํ๋ ์์ผํต์ ์ ๋ํด์ ๊ณต๋ถํด๋ณด๊ณ ์ถ์์ต๋๋ค.
์ ํ
- URLSessionWebsocketTask
ํ์ต๋ด์ฉ
final class WebSocket: NSObject {
static let shared = WebSocket()
var url: URL?
// ์ฐ๊ฒฐ์ด ๋๊ฒผ์ ๋, ์์ผ์ฐ๊ฒฐ๋ ๋์.
private var webSocketTask: URLSessionWebSocketTask? {
didSet { oldValue?.cancel(with: .goingAway, reason: nil)}
}
private var timer: Timer?
private override init() {}
func openWebSocket() throws {
// URLSessionConfiguration์ ํตํด ํค๋๋ฅผ ๋ฃ์.
let configuration = URLSessionConfiguration.default
guard let accessToken = JWTManager.shared.get()?.accessToken else { return }
configuration.httpAdditionalHeaders = ["Authorization": "Bearer \(accessToken)"]
guard let url = url else { throw WebSocketError.invalidURL }
let urlSession = URLSession(configuration: configuration)
let webSocketTask = urlSession.webSocketTask(with: url)
// ์์ผํต์ ์์.
webSocketTask.resume()
self.webSocketTask = webSocketTask
self.startPing() // ํ์ ํตํด ์์ผ ๋๊น ๋ฐฉ์ง
self.receiveEvent() // receive ์ด๋ฒคํธ ๋ฐ์ ๊ฐ์ง
}
func closeWebSocket() {
self.webSocketTask = nil
self.timer?.invalidate()
}
private func send(data: Data) {
self.webSocketTask?.send(.data(data)) { error in
if let error = error {
print("์ค๋ฅ ๋ฐ์: \(error)")
} else {
print("๋ฉ์์ง ์ ์ก ์๋ฃ")
}
}
}
func receiveEvent() {
guard let webSocketTask = self.webSocketTask else {
return
}
webSocketTask.receive { result in
switch result {
case .success(let message):
if case .string(let text) = message {
if let jsonData = text.data(using: .utf8) {
do {
let decoder = JSONDecoder()
let message = try decoder.decode(ReceiveMessageDTO.self, from: jsonData)
MessageManager.shared.messageSubject.send(message)
} catch {
dump(error)
}
}
}
self.receiveEvent()
case .failure(let error):
print("Error receiving message: \(error)")
}
}
}
private func startPing() {
self.timer?.invalidate()
self.timer = Timer.scheduledTimer(
withTimeInterval: 10,
repeats: true,
block: { [weak self] _ in self?.ping() }
)
}
private func ping() {
self.webSocketTask?.sendPing(pongReceiveHandler: { [weak self] error in
guard error != nil else { return }
self?.startPing()
})
}
}
๋ฉ์ธ์ง๋ฅผ json์ผ๋ก ๋ณ๊ฒฝํด์ send() ํธ์ถ
func sendJoinRoom(roomID: Int) {
let joinRoomEvent = """
{
"event": "join-room",
"data": {
"room_id": \(roomID)
}
}
"""
guard let jsonData = joinRoomEvent.data(using: .utf8) else { return }
send(data: jsonData)
}
func sendMessage(roomID: Int, sender: String, message: String, count: Int) {
let sendMessageEvent = """
{
"event": "send-message",
"data": {
"room_id": \(roomID),
"message": "\(message)",
"sender": "\(sender)",
"count": \(count)
}
}
"""
guard let jsonData = sendMessageEvent.data(using: .utf8) else { return }
send(data: jsonData)
}