Spec-Zone .ru
спецификации, руководства, описания, API

Библиотека разработчика XCode

Разработчик

Swift язык программирования

iBook
На этой странице

Перечисления

Перечисление определяет общий тип для группы связанных значений и позволяет Вам работать с теми значениями безопасным с точки зрения типов способом в Вашем коде.

Если Вы будете знакомы с C, то Вы будете знать, что перечисления C присваивают связанные имена к ряду целочисленных значений. Перечисления в Swift намного более гибки, и не должны предоставлять значение каждому элементу перечисления. Если значение (известный как «необработанное» значение) предоставлено для каждого элемента перечисления, значение может быть строкой, символом или значением любого целочисленного или типа с плавающей точкой.

Также элементы перечисления могут указать присваиваемые значения любого типа, который будет сохранен вместе с каждым различным задействованным значением, очень как объединения, или варианты делают на других языках. Можно определить единый набор связанных элементов как часть одного перечисления, каждый из которых имеет различный набор значений надлежащих типов, связанных с ним.

Перечисления в Swift являются первоклассными типами самостоятельно. Они принимают много функций, традиционно поддерживавших только классами, такими как вычисленные свойства для предоставления дополнительной информации о текущей стоимости перечисления и методов экземпляра обеспечить функциональность, связанную со значениями, которые представляет перечисление. Перечисления могут также определить инициализаторы для обеспечения начального задействованного значения; может быть расширен для расширения их функциональности вне их исходной реализации; и может соответствовать протоколам для обеспечения стандартной функциональности.

Для больше на этих возможностях, посмотрите Свойства, Методы, Инициализацию, Расширения и Протоколы.

Синтаксис перечисления

Вы представляете перечисления с enum ключевое слово и место их все определение в паре фигурных скобок:

  • enum SomeEnumeration {
  • // enumeration definition goes here
  • }

Вот пример для четырех основных моментов компаса:

  • enum CompassPoint {
  • case North
  • case South
  • case East
  • case West
  • }

Значения, определенные в перечислении (такой как North, South, East, и West) задействованные значения (или элементы) того перечисления. case ключевое слово указывает, что новая строка задействованных значений собирается быть определенной.

Многократные задействованные значения могут появиться на одной строке, разделенной запятыми:

  • enum Planet {
  • case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
  • }

Каждое определение перечисления определяет совершенно новый тип. Как другие типы в Swift, их имена (такой как CompassPoint и Planet) должен запуститься с прописной буквы. Дайте перечисление, вводит исключительные а не множественные имена, так, чтобы они читали как самоочевидные:

  • var directionToHead = CompassPoint.West

Тип directionToHead выведен, когда это инициализируется с одним из возможных значений CompassPoint. Один раз directionToHead объявляется как a CompassPoint, можно установить его в различное CompassPoint значение с помощью более короткого точечного синтаксиса:

  • directionToHead = .East

Тип directionToHead уже известен, и таким образом, можно отбросить тип при установке его значения. Это делает для очень читаемого кода при работе с явно введенными перечислимыми величинами.

Соответствие перечислимых величин с оператором переключения

Можно соответствовать отдельные перечислимые величины a switch оператор:

  • directionToHead = .South
  • switch directionToHead {
  • case .North:
  • println("Lots of planets have a north")
  • case .South:
  • println("Watch out for penguins")
  • case .East:
  • println("Where the sun rises")
  • case .West:
  • println("Where the skies are blue")
  • }
  • // prints "Watch out for penguins"

Можно считать этот код как:

“Рассмотрите значение directionToHead. В случае, где это равняется .North, печать "Lots of planets have a north". В случае, где это равняется .South, печать "Watch out for penguins".”

… и т.д.

Как описано в Потоке управления, a switch оператор должен быть исчерпывающим при рассмотрении элементов перечисления. Если case для .West опущен, этот код не компилирует, потому что он не рассматривает полный список CompassPoint элементы. Требование полноты гарантирует, что случайно не опущены элементы перечисления.

Когда не является надлежащим обеспечить a case для каждого элемента перечисления можно обеспечить a default случай для покрытия любых элементов, не адресующихся явно:

  • let somePlanet = Planet.Earth
  • switch somePlanet {
  • case .Earth:
  • println("Mostly harmless")
  • default:
  • println("Not a safe place for humans")
  • }
  • // prints "Mostly harmless"

Присваиваемые значения

Примеры в предыдущем разделе показывают, как элементы перечисления являются определенным (и введенный) значение самостоятельно. Можно установить константу или переменный к Planet.Earth, и проверьте на это значение позже. Однако иногда полезно быть в состоянии сохранить присваиваемые значения других типов рядом с этими задействованными значениями. Это позволяет Вам хранить дополнительную пользовательскую информацию вместе с задействованным значением и разрешает этой информации варьироваться каждый раз, когда Вы используете тот элемент в своем коде.

Можно определить перечисления Swift для хранения присваиваемых значений любого данного типа, и типы значения могут отличаться для каждого элемента перечисления в случае необходимости. Перечисления, подобные им, известны как дизъюнктные объединения, размеченные объединения или варианты в других языках программирования.

Например, предположите, что система отслеживания ресурсов должна отследить продукты двумя различными типами штрихкода. Некоторые продукты маркируются одномерными штрихкодами в формате UPC-A, использующем числа 0 к 9. Каждый штрихкод имеет цифру «системы счисления», сопровождаемую пятью “цифрами” кода производителя и пятью цифрами «кода продукта». Они сопровождаются цифрой «проверки», чтобы проверить, что код был отсканирован правильно:

image: ../Art/barcode_UPC_2x.png

Другие продукты маркируются двухмерными штрихкодами в формате QR-кода, который может использовать любой символ ISO 8859-1 и может закодировать строку до 2 953 символов в длину:

image: ../Art/barcode_QR_2x.png

Было бы удобно для системы отслеживания ресурсов быть в состоянии сохранить штрихкоды UPC-A как кортеж четырех целых чисел и штрихкоды QR-кода как строка любой длины.

В Swift перечисление для определения штрихкодов продукта любого типа могло бы быть похожим на это:

  • enum Barcode {
  • case UPCA(Int, Int, Int, Int)
  • case QRCode(String)
  • }

Это может быть считано как:

“Определите вызванный тип перечисления Barcode, который может взять любого значение UPCA с присваиваемым значением типа (Int, Int, Int, Int), или значение QRCode с присваиваемым значением типа String.”

Это определение не предоставляет никому фактическому Int или String значения — это просто определяет тип присваиваемых значений это Barcode константы и переменные могут сохранить, когда они равны Barcode.UPCA или Barcode.QRCode.

Новые штрихкоды могут тогда быть созданы с помощью любого типа:

  • var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)

Этот пример создает новую вызванную переменную productBarcode и присваивает его значение Barcode.UPCA со связанным значением кортежа (8, 85909, 51226, 3).

Тот же продукт может быть присвоен другой тип штрихкода:

  • productBarcode = .QRCode("ABCDEFGHIJKLMNOP")

В этой точке, оригинале Barcode.UPCA и его целочисленные значения заменяются новым Barcode.QRCode и его строковое значение. Константы и переменные типа Barcode может сохранить любого a .UPCA или a .QRCode (вместе с их присваиваемыми значениями), но они могут только сохранить одного из них в любой момент времени.

Различные типы штрихкода могут быть проверены с помощью оператора переключения, как прежде. На сей раз, однако, присваиваемые значения могут быть извлечены как часть оператора переключения. Вы извлекаете каждое присваиваемое значение как константу (с let префикс) или переменная (с var префикс) для использования в switch организация случая:

  • switch productBarcode {
  • case .UPCA(let numberSystem, let manufacturer, let product, let check):
  • println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
  • case .QRCode(let productCode):
  • println("QR code: \(productCode).")
  • }
  • // prints "QR code: ABCDEFGHIJKLMNOP."

Если все присваиваемые значения для элемента перечисления извлечены как константы, или если все извлечены как переменные, можно поместить сингл var или let аннотация перед именем элемента, для краткости:

  • switch productBarcode {
  • case let .UPCA(numberSystem, manufacturer, product, check):
  • println("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
  • case let .QRCode(productCode):
  • println("QR code: \(productCode).")
  • }
  • // prints "QR code: ABCDEFGHIJKLMNOP."

Необработанные значения

Пример штрихкода в Присваиваемых значениях показывает, как элементы перечисления могут объявить, что хранят присваиваемые значения различных типов. Как альтернатива присваиваемым значениям, элементы перечисления могут приехать предварительно заполненные со значениями по умолчанию (названный необработанными значениями), которые являются всем тем же типом.

Вот пример, хранящий необработанные значения ASCII рядом с именованными элементами перечисления:

  • enum ASCIIControlCharacter: Character {
  • case Tab = "\t"
  • case LineFeed = "\n"
  • case CarriageReturn = "\r"
  • }

Здесь, сырые данные оценивают за вызванное перечисление ASCIIControlCharacter определяются, чтобы иметь тип Character, и установлены в некоторые более общие управляющие символы ASCII. Character значения описаны в Строках и Символах.

Обратите внимание на то, что необработанные значения не являются тем же как присваиваемыми значениями. Необработанные значения установлены в предзаполненные значения при первом определении перечисления в коде, как эти три кода ASCII выше. Необработанное значение для определенного элемента перечисления всегда является тем же. Присваиваемые значения установлены, когда Вы создаете новую константу или переменный на основе одного из элементов перечисления и можете отличаться каждый раз, когда Вы делаете так.

Необработанные значения могут быть строками, символами или любым из целочисленных или типов числа с плавающей точкой. Каждое необработанное значение должно быть уникальным в своем объявлении перечисления. Если никакое значение не указано для некоторых элементов перечисления, когда целые числа используются для необработанных значений, они автоинкремент.

Перечисление ниже является улучшением ранее Planet перечисление, с необработанными целочисленными значениями для представления порядка каждой планеты от солнца:

  • enum Planet: Int {
  • case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
  • }

Автоприращение означает это Planet.Venus имеет необработанное значение 2, и т.д.

Получите доступ к необработанному значению элемента перечисления с rawValue свойство:

  • let earthsOrder = Planet.Earth.rawValue
  • // earthsOrder is 3

Инициализация от необработанного значения

При определении перечисления с помощью типа необработанного значения перечисление автоматически получает инициализатор, принимающий значение типа необработанного значения (в качестве параметра вызванный rawValue) и возвраты или элемент перечисления или nil. Можно использовать этот инициализатор, чтобы попытаться создать новый экземпляр перечисления.

Этот пример идентифицирует Урана от своего необработанного значения 7:

  • let possiblePlanet = Planet(rawValue: 7)
  • // possiblePlanet is of type Planet? and equals Planet.Uranus

Не все возможные Int значения найдут соответствующую планету, как бы то ни было. Из-за этого необработанный инициализатор значения всегда возвращает дополнительный элемент перечисления. В примере выше, possiblePlanet имеет тип Planet?, или “дополнительный Planet.”

При попытке найти планету с позицией 9, дополнительное Planet значение, возвращенное необработанным инициализатором значения, будет nil:

  • let positionToFind = 9
  • if let somePlanet = Planet(rawValue: positionToFind) {
  • switch somePlanet {
  • case .Earth:
  • println("Mostly harmless")
  • default:
  • println("Not a safe place for humans")
  • }
  • } else {
  • println("There isn't a planet at position \(positionToFind)")
  • }
  • // prints "There isn't a planet at position 9"

Этот пример использует дополнительную привязку, чтобы попытаться получить доступ к планете с необработанным значением 9. Оператор if let somePlanet = Planet(rawValue: 9) создает дополнительное Planet, и наборы somePlanet к значению этого дополнительного Planet если это может быть получено. В этом случае не возможно получить планету с позицией 9, и так else ответвление выполняется вместо этого.