I have a service which connects to server using socket and stays connected,I used this enum to manage connection state:enum ConnectionState {  case none, connecting, failed(Error), connected, disconnected(Error), blocked}I wanted to have connectionState as property to know current connection state of service but in extension of service provider class.Why in extension and not in class itself?Because ServiceProvider class is not Swift class, its ObjC class and there is no way we I can declare ConnectionState swift enum with associated values in ObjC class.So I used associative stored property in swift extension, but as ConnectionState has associated values I need to do little more.First I created extension to enum to make dictionary convertible as:extension ConnectionState {  var dictPresentation: [String: Error?] {    switch self {    case .none: return [none: nil]    case .connecting: return [connecting: nil]    case .failed(let error): return [failed: error]    case .connected: return [connected: nil]    case .disconnected(let error): return [disconnected: error]    case .blocked: return [blocked: nil]    }  }  init(dict: [String: Error?]) {    assert(!dict.isEmpty, dict must contain one key)    let key = dict.keys.first!    let error: Error? = dict[key] ?? nil    switch key {    case none: self = .none    case connecting: self = .connecting    case failed: self = .failed(error!)    case connected: self = .connected    case disconnected: self = .disconnected(error!)    case blocked: self = .blocked    default:        assert(false, wrong key in dict)        self = .none    }  }}Then used it in service provider class extension as:private var ConnectionStateHolderKey: UInt8 = 7extension ServiceProvider {  private var _connectionStateHolder: NSDictionary {    get {        if let connectionStateDict = objc_getAssociatedObject(self, &ConnectionStateHolderKey) as? NSDictionary {            return connectionStateDict        }        //return [none: nil] gives error nil is not compatible with expected dictionary value type 'Any'        //return [none: nil as Any] gifs error Nil is not compatible with 'Any' in coercion        let dict = NSDictionary()        dict.setValue(nil, forKey: none)        return dict//default state = none    }    set {        objc_setAssociatedObject(self, &ConnectionStateHolderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)    }  }  var connectionState: ConnectionState {    get {        return ConnectionState(dict: _connectionStateHolder as! [String : Error?])    }    set {      _connectionStateHolder = newValue.dictPresentation as NSDictionary    }  }}Is there anything that can be used to simplify this code and avoid dictionary conversion?Any suggestions that can improve this code are welcomed!
Enum with associated value as stored property in Swift extension
swift;enum;extension methods;properties
First note that your var connectionState is  computed property,not a stored property. It is computed using the get and setmethods. Extensions cannot add stored properties to a type.Your current implementation crashes if the connection state is retrievedwithout having been set before:let provider = ServiceProvider()print(provider.connectionState)because atlet dict = NSDictionary()dict.setValue(nil, forKey: none)dict is an immutable dictionary. Making it mutable does not solve theproblem let dict = NSMutableDictionary()dict.setValue(nil, forKey: none)because the second statement has no effect and therefore the assertionassert(!dict.isEmpty, dict must contain one key)fails. You want to create a NSDictionary which  when bridged to [String: Error?] becomes [none: nil]. The difficulty here is that thevalue type of the Swift dictionary is an optional. But it is possible,using NSNull():    get {        if let connectionStateDict = objc_getAssociatedObject(self, &ConnectionStateHolderKey) as? NSDictionary {            return connectionStateDict        }        return [none: NSNull()]    }(compare SE-0140 Warn when Optional converts to Any, and bridge Optional As Its Payload Or NSNull).But: All these conversions between enum, Swift dictionary and NSDictionaryare actually not needed, you can achieve the same much simpler.As stated in Swift Blog: Objective-C id as Swift Any,The Objective-C bridge in Swift 3 can in turn present any Swift value as an id-compatible object to Objective-C.This means that you can pass an enum ConnectionState directly to objc_setAssociatedObject()and conditionally cast the return value from objc_getAssociatedObject() back to the enum.The Swift runtime automatically wraps the value into a class.(AnyObject not working in Xcode8 beta6?on Stack Overflow contains further information and links.)So this is everything you need:enum ConnectionState {    case none, connecting, failed(Error), connected, disconnected(Error), blocked}private var ConnectionStateHolderKey: UInt8 = 7extension ServiceProvider {    var connectionState: ConnectionState {        get {            if let connectionState = objc_getAssociatedObject(self, &ConnectionStateHolderKey) as? ConnectionState {                return connectionState            }            return .none        }        set {            objc_setAssociatedObject(self, &ConnectionStateHolderKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)        }    }}More suggestions:Use the nil-coalescing operator ?? to provide a default value in the getter method.Restrict the scope of the associated objects key by making it a static property inside extension ServiceProvider.Then the code would look like this:extension ServiceProvider {    private struct Keys {        static var connectionState : UInt8 = 7    }     var connectionState: ConnectionState {        get {            return (objc_getAssociatedObject(self, &ServiceProvider.Keys.connectionState) as? ConnectionState) ?? .none        }        set {            objc_setAssociatedObject(self, &ServiceProvider.Keys.connectionState, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)        }    }}Finally: Your enum has a case none for no state. But the Swift wayof representing no value is to use an optional:enum ConnectionState {    case connecting, failed(Error), connected, disconnected(Error), blocked}extension ServiceProvider {    private struct Keys {        static var connectionState : Int = 0    }     var connectionState: ConnectionState? {        get {            return objc_getAssociatedObject(self, &ServiceProvider.Keys.connectionState) as? ConnectionState        }        set {            objc_setAssociatedObject(self, &ServiceProvider.Keys.connectionState, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)        }    }}