Reputation: 8406
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
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
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