Switch: Enum Switch issue: не является членом int
Я пишу свой первый проект в Swift (я занимаюсь ObjectiveC в течение многих лет), и по какой-то причине я не могу понять, почему мой перечислитель и коммутатор не работают.
enum ContactViewMode : Int
{
case ViewModeFavourite = 0
case ViewModeRecent = 1
case ViewModeContacts = 2
}
Недвижимость
@IBInspectable var contactViewMode : Int!
Переключатель
switch contactViewMode {
case ContactViewMode.ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode.ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
Ошибка, которую я получаю,
Событие Enum 'ViewModeFavourite' не является членом типа 'Int!'
Итак, я изменил его на это, поскольку это не Int! (Мне нужен Int! Для раскадровки)
var contactMode:Int = contactViewMode
switch contactMode {
case .ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
Тогда я получаю
Шаблон case Enum не может соответствовать значениям типа non-enum 'Int'
Ответы
Ответ 1
Вы должны объявить contactViewMode
как contactViewMode
, а не Int
.
Если вы действительно хотите, чтобы он был Int
, вам нужно изменить случаи в своем коммутаторе, сравнив переменную с свойством rawValue
в случаях перечисления:
switch contactViewMode {
case ContactViewMode.ViewModeFavourite.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode.ViewModeRecent.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
но если у вас нет веских оснований для этого, я бы не рекомендовал
Ответ 2
Другие ответы не в состоянии использовать сильную типизацию Swifts. Обратите внимание, что все они имеют регистр по default
в своем switch
. Однако во время компиляции Swift знает, охватывали ли вы все случаи enum
или нет, что делает ненужным случай по default
.
Это полезная функция языка. Представьте, что вы добавите дополнительный case
к своему enum
на более позднем этапе. Компилятор будет жаловаться и указывать на все switch
, которые не рассматривают этот конкретный case
.
Как мы можем воспользоваться преимуществами строгой типизации Swifts?
Во-первых, давайте исправим наименование вашего перечисления. Поскольку я предполагаю, что вы ContactView
класс ContactView
(и, в отличие от Objective-C, он действительно должен быть внутри него), вы можете назвать enum
просто Mode
. Нет необходимости упоминать ViewMode
в этих случаях. Таким образом, вы получите более чистый идиоматичный тип.
enum Mode: Int {
case favourite
case recent
case contacts
}
Нам нужно выполнить switch
в Mode
, а не в Int
. Ваш Mode
является RawRepresentable
, и поэтому вы можете сделать:
guard let m = Mode(rawValue: contactViewMode) else { /* handle the situation */ }
switch m {
case .favourite: /* handle case */
case .recent: /* handle case */
case .contacts: /* handle case */
}
Вот и все, что нужно сделать - вместо того, чтобы rawValue
, rawValue
получите rawValue
Mode
а затем rawValue
его.
Ответ 3
Это сработало для меня:
У меня есть перечисление вроде этого:
enum Proximity{
case Unknown
case Immediate
case Near
case Far
}
Затем появится переключатель, который выглядит так:
switch b.proximity as Proximity {
case Proximity.Immediate:
if b.rssi == -30 && b.accuracy == 0.2345{
closestBeacon = b
}
case Proximity.Near:
return
case Proximity.Far:
return
default:
return
}
Im цикл через массив объектов "b", которые имеют свойство близости.
Ответ 4
Перечисления - это типы. Просто потому, что вы четко указываете, что одиночные значения перечисления могут быть отлиты до Int
, не делает его действительным для объявления contactViewMode
a Int!
. Типы просто не совпадают.
Итак, объявляйте contactViewMode
как contactViewMode
, используйте свой первый оператор switch
и добавьте в Int!
, когда он действительно нужен для раскадровки, или используйте второй switch
, но не используйте .ViewModeFacourite
et al, но соответствующее значение Int
.
var contactMode:Int = contactViewMode
switch contactMode {
case ContactViewMode.ViewModeFavourite.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case ContactViewMode..ViewModeRecent.rawValue:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
Ответ 5
Вы не можете напрямую сопоставлять Int
с enum
. Вместо этого вам нужно преобразовать ContactViewMode
в Int
с свойством .rawValue
, ИЛИ преобразовать Int
в ContactViewMode
с инициализатором init(rawValue:)
.
Последний пример:
switch ContactViewMode(rawValue: contactViewMode) {
case .Some(.ViewModeFavourite):
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .Some(.ViewModeRecent):
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}
потому что ContactViewMode(rawValue:)
возвращает опции, нам нужно .Some()
.
Ответ 6
Вы можете просто использовать contactViewMode и создать новую ContactViewMode
типа ContactViewMode
в случае, если значение contactViewMode
приходит откуда-то еще, и оно должно быть int
.
let contactMode :ContactViewMode = ContactViewMode(rawValue: contactViewMode)!
Теперь вы можете легко использовать переключатель, как показано ниже:
switch contactMode {
case .ViewModeFavourite:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
case .ViewModeRecent:
contacts = DBManager.getFavouriteContacts() as [ContactEntity]
default:
contacts = DBManager.getAllContacts() as [ContactEntity]
}