Tometoyou
Tometoyou

Reputation: 8406

Enum being initialised when it shouldn't be

I am trying to create a manager for errors returned from a livestreaming framework called OpenTok. For some reason, the enums that represent OpenTok errors are being initialised when they shouldn’t be. For example:

let error = OTSubscriberErrorCode(rawValue: 1010)
// The rawValue is an Int32, I don't know if that makes a difference

This successfully initialises an OTSubscriberErrorCode, however, 1010 is NOT an OTSubscriberErrorCode, it’s an OTPublisherErrorCode, specifically the error code for case sessionDisconnected.

See here for the OTSubscriberErrorCode docs.

See here for the OTPublisherErrorCode docs.

error should be nil but it's not. Why is this happening?

Upvotes: 1

Views: 75

Answers (2)

rob mayoff
rob mayoff

Reputation: 386038

Apple explains this behavior in “Grouping Related Objective-C Constants”:

Enumerations imported using the NS_ENUM macro won't fail when you initialize one with a raw value that does not correspond to an enumeration case. This characteristic facilitates compatibility with C, which allows any value to be stored in an enumeration, including values used internally but not exposed in headers.

Upvotes: 2

Glenn Posadas
Glenn Posadas

Reputation: 13300

OTSubscriberErrorCode is an NS_ENUM written in Objective-C. (Why objective-c NS_ENUM variable automatically have default value)

typedef NS_ENUM(int32_t, OTSubscriberErrorCode ) {
   OTSubscriberSuccess = 0,
   OTConnectionTimedOut = 1542,
   OTSubscriberSessionDisconnected = 1541,
   OTSubscriberWebRTCError = 1600,
   OTSubscriberServerCannotFindStream = 1604,
   OTSubscriberStreamLimitExceeded = 1605,
   OTSubscriberInternalError = 2000,
};

You could make a Swift version of that enum like so:

enum OTSubscriberErrorCodeSwift: Int32 {
    case success = 0
    case timeout = 1542
    case sessionDisconnected = 1541
    case webRTCError = 1600
    case cannotFindStream = 1604
    case streamLimitExceeded = 1605
    case internalError = 2000
}

So that when you attempt to make an error out of that "Swifty" enum with an invalid rawValue, you'll get nil.

let error = OTSubscriberErrorCodeSwift(rawValue: 1010) // nil

EDIT

When using Objective-C's NS_ENUM, you could just use switch statement, like so:

let error = OTSubscriberErrorCode(rawValue: 1010)
        if let error = error {
            switch error {
            case .subscriberSuccess: print("subscriberSuccess")
            case .connectionTimedOut: print("timeout")
            case .subscriberSessionDisconnected: print("subscriberSessionDisconnected")
            case .subscriberWebRTCError: print("subscriberWebRTCError")
            case .subscriberServerCannotFindStream: print("subscriberServerCannotFindStream")
            case .subscriberStreamLimitExceeded: print("subscriberStreamLimitExceeded")
            case .subscriberInternalError: print("subscriberInternalError")
            default: print("NO ERROR")
            }
        }

In the case above, you'll get to the default. From there, do whatever you wanted to do as if the error variable is nil.

Upvotes: 1

Related Questions