URLSessionWebSocketTask custom close code

Is there a good way to access the web socket task actual close code?
when looking at the task delegate:

urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?)

I can see my custom code _closeCode = (long long) 4231 but the delegate (and the task's) closeCode variable is an enum (URLSessionWebSocketTask.CloseCode) so it have a fallback to the default invalid (0) for unknown values.
I wonder if using

webSocketTask.value(forKey: "_closeCode")

Count as accessing private api, or if there is a cleaner way to access this raw value.

Accepted Reply

Using webSocketTask.value(forKey: "_closeCode") seems to be a good enough solution

No it is not. It’s not safe to KVC to read private properties on system types.

About using the enum's raw value, the thing is that I can't use any custom close code because enum, by definition, have a close set of cases.

That’s only true within a module. Swift supports extensible enums across module boundaries. That is, a module can export an enum with a set of cases and:

  • Define private cases

  • Add new cases in new versions of the module

So this ‘closed set of cases’ view of enums is only valid within a module, or if the enum is annotated with @frozen.

If want to test for a specific close code, you can either write this:

func urlSession(…, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, …) {
    if closeCode.rawValue == 4231 {
        … your code here …
    }
}

or this:

func urlSession(…, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, …) {
    let myCustomCloseCode = URLSessionWebSocketTask.CloseCode(rawValue: 4231)!
    if closeCode == myCustomCloseCode {
        … your code here …
    }
}

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

Get this from the rawValue property of the CloseCode:

let closeCode = URLSessionWebSocketTask.CloseCode.abnormalClosure
print(closeCode.rawValue)   // 1006

ps If you’re exploring the boundaries of WebSockets, you will eventually run into places where URLSession tops out. I generally recommend that folks use Network framework for WebSockets. See TN3151 Choosing the right networking API and this thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks @eskimo ,
I'll give this article a read, but I have to admit that I find the URLSession implementation quite straightforward, at least until now.
About using the enum's raw value, the thing is that I can't use any custom close code because enum, by definition, have a close set of cases.
Using webSocketTask.value(forKey: "_closeCode") seems to be a good enough solution, but I'm not sure if it counts as using private api.

Using webSocketTask.value(forKey: "_closeCode") seems to be a good enough solution

No it is not. It’s not safe to KVC to read private properties on system types.

About using the enum's raw value, the thing is that I can't use any custom close code because enum, by definition, have a close set of cases.

That’s only true within a module. Swift supports extensible enums across module boundaries. That is, a module can export an enum with a set of cases and:

  • Define private cases

  • Add new cases in new versions of the module

So this ‘closed set of cases’ view of enums is only valid within a module, or if the enum is annotated with @frozen.

If want to test for a specific close code, you can either write this:

func urlSession(…, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, …) {
    if closeCode.rawValue == 4231 {
        … your code here …
    }
}

or this:

func urlSession(…, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, …) {
    let myCustomCloseCode = URLSessionWebSocketTask.CloseCode(rawValue: 4231)!
    if closeCode == myCustomCloseCode {
        … your code here …
    }
}

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"