Enum of structs in Swift 3.0

拈花ヽ惹草 提交于 2019-12-01 00:14:25

问题


I am trying to create an enum of a struct that I would like to initialize:

struct CustomStruct {
    var variable1: String
    var variable2: AnyClass
    var variable3: Int

    init (variable1: String, variable2: AnyClass, variable3: Int) {
        self.variable1 = variable1
        self.variable2 = variable2
        self.variable3 = variable3
    }
}

enum AllStructs: CustomStruct {
    case getData
    case addNewData

    func getAPI() -> CustomStruct {
        switch self {
            case getData:
                return CustomStruct(variable1:"data1", variable2: SomeObject.class, variable3: POST)

            case addNewData:
                // Same to same

            default:
                return nil
        }
    }
}

I get the following errors:

Type AllStructs does not conform to protocol 'RawRepresentable'

I am assuming that enums cannot be used this way. We must use primitives.


回答1:


It should be:

struct CustomStruct {
    var apiUrl: String
    var responseType: AnyObject
    var httpType: Int

    init (variable1: String, variable2: AnyObject, variable3: Int) {
        self.apiUrl = variable1
        self.responseType = variable2
        self.httpType = variable3
    }
}

enum MyEnum {
    case getData
    case addNewData

    func getAPI() -> CustomStruct {
        switch self {
        case .getData:
            return CustomStruct(variable1: "URL_TO_GET_DATA", variable2: 11 as AnyObject, variable3: 101)
        case .addNewData:
            return CustomStruct(variable1: "URL_TO_ADD_NEW_DATA", variable2: 12 as AnyObject, variable3: 102)
        }
    }
}

Usage:

let data = MyEnum.getData
let myObject = data.getAPI()

// this should logs: "URL_TO_GET_DATA 11 101"
print(myObject.apiUrl, myObject.responseType, myObject.httpType)

Note that upon Naming Conventions, struct should named as CustomStruct and enum named as MyEnum.

In fact, I'm not pretty sure of the need of letting CustomStruct to be the parent of MyEnum to achieve what are you trying to; As mentioned above in the snippets, you can return an instance of the struct based on what is the value of the referred enum.




回答2:


I'm not commenting on the choice to use an enum here, but just explaining why you got that error and how to declare an enum that has a custom object as parent.

The error shows you the problem, CustomStruct must implement RawRepresentable to be used as base class of that enum.

Here is a simplified example that shows you what you need to do:

struct CustomStruct : ExpressibleByIntegerLiteral, Equatable {
    var rawValue: Int = 0

    init(integerLiteral value: Int){
        self.rawValue = value
    }

    static func == (lhs: CustomStruct, rhs: CustomStruct) -> Bool {
        return
            lhs.rawValue == rhs.rawValue
    }
}


enum AllStructs: CustomStruct {
    case ONE = 1
    case TWO = 2
}

A few important things that we can see in this snippet:

  1. The cases like ONE and TWO must be representable with a Swift literal, check this Swift 2 post for a list of available literals (int,string,array,dictionary,etc...). But please note that in Swift 3, the LiteralConvertible protocols are now called ExpressibleByXLiteral after the Big Swift Rename.
  2. The requirement to implement RawRepresentable is covered implementing one of the Expressible protocols (init?(rawValue:) will leverage the initializer we wrote to support literals).
  3. Enums must also be Equatable , so you'll have to implement the equality operator for your CustomStruct base type.



回答3:


Did you try conforming to RawRepresentable like the error is asking?

Using JSON representation should work for variable1 and variable3. Some extra work may be required for variable2.

struct CustomStruct: RawRepresentable {
    var variable1: String
    var variable2: AnyClass
    var variable3: Int
    init?(rawValue: String) {
        guard let data = rawValue.data(using: .utf8) else {
            return nil
        }
        guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
            return nil
        }
        self.variable1 = (json["variable1"] as? String) ?? ""
        self.variable2 = (json["variable2"] as? AnyClass) ?? AnyClass()
        self.variable3 = (json["variable3"] as? Int) ?? 0
    }
    var rawValue: String {
        let json = ["variable1": self.variable1,
                    "variable2": self.variable2,
                    "variable3": self.variable3
                    ]
        guard let data = try? JSONSerialization.data(withJSONObject: json, options: []) else {
            return ""
        }
        return String(data: data, encoding: .utf8) ?? ""
    }
}



回答4:


According to the documentation:

If a value (known as a “raw” value) is provided for each enumeration case, the value can be a string, a character, or a value of any integer or floating-point type.

So yes, you cannot set a struct type to be enum's raw value.

In your case I would suggest using string as the enum raw value and some dictionary mapping these strings to CUSTOM_STRUCT type.



来源:https://stackoverflow.com/questions/41922097/enum-of-structs-in-swift-3-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!