Перечень структур в Swift 3.0
Я пытаюсь создать перечисление структуры, которую я хотел бы инициализировать:
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
}
}
}
Я получаю следующие ошибки:
Тип AllStructs не соответствует протоколу 'RawRepresentable'
Я предполагаю, что перечисления не могут быть использованы таким образом. Мы должны использовать примитивы.
5 ответов
Так должно быть:
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)
}
}
}
Использование:
let data = MyEnum.getData
let myObject = data.getAPI()
// this should logs: "URL_TO_GET_DATA 11 101"
print(myObject.apiUrl, myObject.responseType, myObject.httpType)
Обратите внимание, что в соответствии с Соглашениями об именах, структура должна называться как CustomStruct
и enum, названный как MyEnum
,
На самом деле, я не совсем уверен в необходимости CustomStruct
быть родителем MyEnum
достичь того, что вы пытаетесь; Как упомянуто выше во фрагментах, вы можете вернуть экземпляр структуры, основываясь на значении указанного перечисления.
Я не комментирую выбор использования перечисления здесь, а просто объясняю, почему вы получили эту ошибку и как объявить перечисление, в котором пользовательский объект является родительским.
Ошибка показывает вам проблему, CustomStruct
должен реализовать RawRepresentable
для использования в качестве базового класса этого перечисления.
Вот упрощенный пример, который показывает вам, что вам нужно сделать:
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
}
Несколько важных вещей, которые мы можем увидеть в этом фрагменте:
- Случаи, такие как ONE и TWO,должны быть представлены с литералом Swift, проверьте в этом посте Swift 2 список доступных литералов (int,string,array,dictionary и т. Д.). Но учтите, что в Swift 3 протоколы LiteralConvertible теперь называются ExpressibleByXLiteral после переименования Big Swift.
- Требование к реализации
RawRepresentable
покрывается реализацией одного из экспрессируемых протоколов (init?(rawValue:)
будет использовать инициализатор, который мы написали для поддержки литералов). - Перечисления также должны быть Equatable, поэтому вам придется реализовать оператор равенства для вашего
CustomStruct
базовый тип.
Согласно документации:
Если значение (известное как "необработанное" значение) предоставляется для каждого случая перечисления, это может быть строка, символ или значение любого целочисленного типа или типа с плавающей запятой.
Так что да, вы не можете установить тип структуры в качестве исходного значения enum.
В вашем случае я бы предложил использовать string
в качестве необработанного значения enum и некоторого словаря, отображающего эти строки в CUSTOM_STRUCT
тип.
Вы пытались соответствовать RawRepresentable, как спрашивает ошибка?
Использование представления JSON должно работать для переменных1 и переменных3. Для переменной2 может потребоваться дополнительная работа.
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) ?? ""
}
}
A bit late on the party but maybe useful for someone else. I would consider to simply use computed variables instead of a struct.
enum MyEnum {
case getData
case addNewData
var variable1: String {
switch self {
case .getData: return "data1"
case .addNewData: return "data2"
}
}
var variable2: Int {
switch self {
case .getData: return 1
case .addNewData: return 2
}
}
// ....
}
Usage:
let data = MyEnum.getData
print (data.variable1) // "data1"