Статьи

Swift From Scratch: коллекции и кортежи

В предыдущей статье вы узнали о переменных, константах и ​​некоторых распространенных типах данных, таких как целые числа, числа с плавающей запятой и строки. В этой статье мы увеличиваем коллекции. Стандартная библиотека Swift определяет три типа коллекций: наборы, массивы и словари. Начнем с массивов.

Если вы знакомы с Objective-C, JavaScript или PHP, разбирать массивы не составит труда. Массив — это упорядоченная, нумерованная коллекция значений. Но есть несколько важных различий между массивами для Swift и другими языками программирования.

Первое важное отличие от массивов в Objective-C заключается в том, что значения, хранящиеся в массиве, всегда имеют одинаковый тип. Сначала это может показаться существенным ограничением, но на самом деле это не так. На самом деле это ограничение имеет важное преимущество. Мы точно знаем, какой тип мы получаем, когда запрашиваем у массива одно из его значений.

Другое ключевое отличие — это тип значений, которые может хранить массив. В Objective-C массив может хранить только значения типа класса. Свифт не имеет этого ограничения. Массив в Swift может хранить строки, целые числа, числа с плавающей запятой и экземпляры классов. Как это работает и почему это возможно в Swift, станет ясно позже в этой серии, когда мы рассмотрим классы и структуры.

Хотя существует несколько способов создания массива, вы должны помнить, что Swift должен знать, какой тип значений вы планируете хранить в массиве. Создайте новую игровую площадку в Xcode, как мы делали в предыдущей статье , и добавьте следующие строки на вашу игровую площадку.

1
2
3
var array1: Array<String>
var array2: [String]
var array3 = [«Apple», «Pear», «Orange»]

Первая и вторая строки означают одно и то же. Вторая строка просто стенография. Квадратные скобки, заключающие ключевое слово String сообщают Swift, что мы объявляем массив, который может содержать только объекты String .

Вы можете прочитать первую строку кода следующим образом: «Мы объявляем переменную с именем array1 типа Array которая может содержать только объекты String ». Двоеточие означает тип .

В третьей строке показано, как инициализировать массив, используя литерал массива. Литералы массивов очень похожи на литералы массивов в Objective-C. Основным отличием является отсутствие символа @ предшествующего квадратным скобкам, и строковых литералов.

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

1
var a = [String](repeating: «Test», count: 5)

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

1
2
var b = Array<String>()
var c = [String]()

Не волнуйтесь, если вы все еще в замешательстве. Мы рассмотрим синтаксис более подробно, как только начнем работать с классами и функциями. В этой статье мы сосредоточимся только на коллекциях.

Один из аспектов Swift, который вы быстро оцените, — как объявлять изменяемые коллекции. Приведенный выше фрагмент кода, например, объявляет три изменяемых массива. Изменяемый массив определяется с помощью ключевого слова var . Это так просто.

Если вы не хотите, чтобы массив был изменяемым, используйте вместо этого ключевое слово let . Swift стремится быть интуитивно понятным и простым в использовании, и его реализация изменчивости является прекрасным примером этой цели.

Чтобы получить доступ к значениям, хранящимся в массиве, мы используем тот же синтаксис нижнего индекса, что и в Objective-C. В следующем примере мы запрашиваем array3 для второго элемента, строку "Pear" .

1
array3[1]

Замена значения, хранящегося в индексе 1 , так же проста, как назначение нового значения с использованием того же синтаксиса синтаксиса. В следующем примере мы заменим "Pear" с индексом 1 на "Peach" .

1
array3[1] = «Peach»

Это возможно только потому, что массив изменчив, то есть мы использовали ключевое слово var для объявления массива. Мутирование константного массива невозможно. Существуют более продвинутые методы манипулирования содержимым массива, но основная концепция та же.

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

1
2
3
4
let a = [1, 2, 3]
let b = [4, 5, 6]
 
let c = a + b

Однако ключевым является то, что значения, хранящиеся в a и b относятся к одному типу. Причина должна быть очевидна к настоящему времени. Как я упоминал ранее, значения, хранящиеся в массиве, должны быть одного типа. Следующий пример приводит к ошибке.

1
2
3
4
let a = [1, 2, 3]
let b = [1.5, 5.2, 6.3]
 
let c = a + b

Чтобы добавить массив в изменяемый массив, мы используем оператор += . Обратите внимание, что операнд справа является массивом. Эта операция не будет работать, если мы удалим квадратные скобки, окружающие 4 .

1
2
var a = [1, 2, 3]
a += [4]

Массивы — это объекты, над которыми вы можете выполнять широкий спектр операций. Массивы предоставляют ряд функций или методов. Чтобы вызвать метод объекта, вы используете точечную запись. Добавьте следующую строку на игровую площадку, чтобы добавить элемент в array3 .

1
array3.append(«Cherry»)

Давайте посмотрим, сколько элементов содержит array3 значение его свойства count . Это выводит 4 на панель результатов.

1
array3.count

Также возможно вставить элемент по определенному индексу, вызвав метод массива insert(_:at:) как показано ниже. Метод insert(_:at:) принимает более одного параметра, и синтаксис на первый взгляд может показаться немного странным.

1
array3.insert(«Prune», at: 2)

Как и Objective-C, Swift поддерживает именованные параметры для улучшения читабельности. В результате код легче читать и понимать, а функции или методы не требуют особого объяснения с точки зрения того, что они делают. Например, понятно, что метод insert(_:at:) вставляет элемент с индексом 2 .

Хотя Swift является более кратким и менее подробным, чем Objective-C, он поддерживает именованные параметры. Если вы используете PHP, Ruby или JavaScript, то к этому, безусловно, нужно привыкнуть.

Что мне действительно нравится в Swift, так это удобные в Ruby свойства и методы стандартной библиотеки Swift. Например, у массива есть свойство isEmpty которое сообщает вам, содержит ли массив какие-либо элементы. Это не что иное, как сокращение для проверки свойства count массива. В результате получается более лаконичный и понятный код.

1
array3.isEmpty

Словари ведут себя очень похоже на словари в Objective-C. В словаре хранится неупорядоченная коллекция значений. Каждое значение в словаре связано с ключом. Другими словами, словарь хранит несколько пар ключ / значение.

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

Объявление словаря похоже на объявление массива. Разница в том, что вам нужно указать тип для ключей и значений. В следующем примере показаны три способа объявления словаря.

1
2
3
var dictionary1: Dictionary<String, Int>
var dictionary2: [String: Int]
var dictionary3 = [«Apple»: 3, «Pear»: 8, «Orange»: 11]

Вторая строка является сокращением для первой строки. Ключи этих словарей должны иметь тип String то время как ожидается, что значения будут иметь тип Int . Ключевое слово var указывает, что словари являются изменяемыми.

Вы можете прочитать первую строку кода следующим образом: «Мы объявляем переменную с именем dictionary1 типа Dictionary которая может содержать только ключи типа String и значения типа Int

Третья строка иллюстрирует, как мы можем инициализировать словарь, используя словарь-литерал. Это похоже на синтаксис, который мы используем в Objective-C, но учтите, что фигурные скобки заменяются квадратными скобками, а литерал не имеет префикс @ .

Доступ к значениям аналогичен доступу к значениям массива. Единственное отличие состоит в том, что вы используете ключ вместо индекса значения, к которому вам нужно получить доступ. Следующий пример иллюстрирует это.

1
2
let value = dictionary3[«Apple»]
print(value)

Вы заметите, что Xcode сообщает нам, что значение value не 3 , а Optional(3) . Что это значит? Swift использует опции для переноса значений, которые могут быть одной из двух, значением или nil . Не беспокойтесь об опциях на данный момент. Мы собираемся сосредоточиться на опциях в следующей статье этой серии. Позвольте мне просто сказать вам, что опционные опции — это еще одна ключевая концепция языка программирования Swift.

Интересно отметить, что синтаксис для доступа к значению словаря идентичен синтаксису массивов, если ключи словаря имеют тип Int . Взгляните на следующий пример, чтобы понять, что я имею в виду.

1
2
var dictionary4 = [0: «Apple», 1: «Pear», 2: «Orange»]
let fruit = dictionary4[0]

Как и для массивов, стандартная библиотека Swift определяет широкий спектр операций, которые вы можете выполнять над словарями. Вы можете запросить у словаря количество пар ключ / значение через его свойство count . Как показано в следующем примере, удаление пары ключ / значение легко и интуитивно понятно. Конечно, это возможно только в том случае, если словарь изменчив.

1
dictionary4.removeValue(forKey: 0)

Когда вы начнете изучать Swift, вы можете столкнуться с фрагментами кода, которые выглядят странно или запутанно. Взгляните на следующую строку, в которой мы сначала объявляем словарь, а затем удаляем его пары ключ / значение.

1
2
3
4
5
6
7
var dictionary = [String: Int]()
 
dictionary[«Oranges»] = 2
dictionary[«Apples»] = 10
dictionary[«Pears»] = 5
 
dictionary = [:]

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

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

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

Работа с наборами немного отличается от работы с массивами. Взгляните на следующие примеры, в которых мы объявляем три набора. Переменная set1 имеет тип Set<String> , набор, который может содержать только значения типа String .

1
2
3
var set1: Set<String>
var set2 = Set<String>()
var set3: Set<String> = [«Apple», «Pear», «Orange»]

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

1
var set3: Set = [«Apple», «Pear», «Orange»]

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

1
set3.count

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

1
set3.insert(«Prune»)

И то же самое относится к удалению элемента из набора.

1
set3.remove(«Orange»)

Вы также можете спросить набор, содержит ли он определенный элемент.

1
set3.contains(«Apple»)

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

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

1
2
3
4
5
import Foundation
 
var currency = («EUR», 0.81)
var time = (Date(), «This is my message.»)
var email = («Bart Jacobs», «[email protected]»)

В первом примере объявляется кортеж с именем currency типа (String, Int) . Второй кортеж time содержит экземпляр Date и строковый литерал. Значения, хранящиеся в email имеют тип String , что означает, что email имеет тип (String, String) .

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

1
2
3
var rate = currency.1
var message = time.1
var name = email.0

Xcode показывает нам индексы каждого значения, хранящиеся в кортеже на панели результатов игровой площадки справа.

Кортежи на детской площадке

Чтобы улучшить читабельность, вы можете назвать значения, хранящиеся в кортеже. В результате вы можете получить доступ к значениям кортежа через их имена вместо их индексов. Объявление кортежа немного отличается в этом случае.

1
2
3
var currency = (name: «EUR», rate: 0.81)
let currencyName = currency.name
let currencyRate = currency.rate

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

1
let (currencyName, currencyRate) = currency

Значение currency в индексе 0 сохраняется в currencyName , а значение в индексе 1 сохраняется в currencyRate . Нет необходимости указывать тип для currencyName и currencyRate поскольку Swift выводит тип из значений, хранящихся в currency . Другими словами, currencyName имеет тип String , а currencyRate имеет тип Float .

Если вас интересуют только конкретные значения кортежа, вы можете использовать подчеркивание, чтобы указать Swift, какие значения вам не интересны.

1
let (currencyName, _) = currency

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

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

Если вы хотите быстро приступить к работе с языком Swift, ознакомьтесь с нашим курсом по созданию приложений для iOS с помощью Swift.

  • стриж
    Создавайте приложения для iOS с помощью Swift
    Маркус Мюльбергер

Или ознакомьтесь с некоторыми другими нашими учебными пособиями и курсами по разработке Swift и iOS!

  • IOS
    Что нового в iOS 10
    Маркус Мюльбергер
  • стриж
    Создайте приложение для iOS с Swift 3: переменные, константы и дополнительные
    Маркус Мюльбергер
  • iOS SDK
    Встроенные покупки в iOS с помощью Swift 3
    Франческо Франкини
  • iOS SDK
    Встроенные покупки в iOS с помощью Swift 3
    Франческо Франкини