Advertisement
  1. Code
  2. Swift

Введение в Swift: часть 2

by
Read Time:18 minsLanguages:

Russian (Pусский) translation by Svetlana (you can also view the original English article)

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

1. Условия и циклы

Если

Если операторы идентичны в Swift и Objective-C, за исключением двух тонких различий:

  • круглые скобки вокруг условной переменной являются необязательными
  • необходимы фигурные скобки

Это единственные различия с утверждениями if в Objective-C.

Диапазоны

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

Полузакрытый диапазон, такой как 1 .. <5, представляет значения 1, 2, 3 и 4, исключая 5. Закрытый диапазон, такой как 1 ... 5, представляет значения 1, 2, 3, 4 и включает в себя 5.

Диапазоны можно использовать для циклов, индекса массива и даже в операторах switch. Взгляните на следующие примеры.

Переключатель

Операторы Switch являются более мощными в Swift, чем в Objective-C. В Objective-C результат выражения оператора switch должен иметь тип integer, а значения каждого оператора case должны быть константой или константным выражением. Это не так в Swift. В Swift операторы case ( положения) могут быть любого типа, включая диапазоны.

В Swift у switch нет операторов break, и он автоматически не переходит от одного случая к другому. При написании оператора switch необходимо следить за тем, чтобы все условия обрабатывались его операторами case (положения), в противном случае это приведет к ошибке компилятора. Надежный способ охватить все условия - включить оператор case (положения) по умолчанию.

Вот пример оператора switch со случаями String:

В Swift операторы case (положения) не проваливаются по умолчанию. Это было обдуманное дизайнерское решение, чтобы избежать распространенных ошибок. Если требуется конкретный случай, вы можете использовать ключевое слово fallthrough, чтобы указать это компилятору.

Это не останавливается здесь. Swift добавляет две другие функции для переключения: привязки значений и предложение where (куда). Привязка значений используется с ключевыми словами case let для привязки константы к соответствующему регистру. Предложение where добавляет дополнительное условие в оператор case, используя ключевое слово where.

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

Первый оператор case, case (пусть x, 0), будет соответствовать значениям, где yaxis равен 0, и любому значению для xaxis, и мы привязываем xaxis к константе x, которая будет использоваться внутри оператора case.

Вот пример, где положение в действии.

2. Функции и замыкания

Функции

Определение функций и замыканий в Swift легко. Разработчики Objective-C знают их лучше как функции и блоки.

В Swift функция параметры могут иметь значения по умолчанию, которые напоминают скриптовых языков, как PHP и Ruby.

Синтаксис функций выглядит следующим образом:

Чтобы написать функцию sayHello, которая принимает имя параметра типа String и возвращает Bool в случае успеха, мы пишем следующее:

Чтобы передать значение по умолчанию для параметра имени, реализация функции должна выглядеть следующим образом:

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

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

Как используются кортежи и как вы от них выигрываете? Рассмотрим другой пример. Давайте изменим вышеупомянутую функцию sayHello, чтобы она возвращала логическое значение в случае успеха, а также полученное сообщение. Мы делаем это путем возвращения кортеж, (Bool, String). Обновленная sayHello функция выглядит так:

Кортежи долгое время были в списке пожеланий многих программистов Objective-C.

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

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

Затворы

Замыкания в Swift такие же, как блоки в Objective-C. Они могут быть определены внутри строки, переданы в качестве параметра или возвращены функциями. Мы используем их точно так же, как и блоки в Objective-C.

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

Замыкания являются типом первого класса, что означает, что они могут передаваться и возвращаться функциями, как и любой другой тип, такой как Int, String, Bool и т. д. Замыкания - это, по сути, блоки кода, которые можно вызывать позже и которые имеют доступ к область, в которой они были определены.

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

Допустим, мы хотим определить замыкание, которое возвращает true, если число четное, тогда это замыкание может выглядеть примерно так:

Закрытие isEven принимает Int в качестве единственного параметра и возвращает Bool. Тип этого замыкания (число: Int) -> Bool или (Int -> Bool) для краткости. Мы можем вызывать isEven в любом месте нашего кода, как если бы мы вызывали блок кода в Objective-C.

Чтобы передать замыкание этого типа в качестве параметра функции, мы используем тип замыкания в определении функции:

В приведенном выше примере параметр verify функции validIfEven является замыканием, которое мы передаем функции.

3. Классы и структуры

Классы

Пришло время поговорить о краеугольном камне объектно-ориентированного программирования, о классах. Классы, как упоминалось ранее, определены в одном файле реализации с расширением .swift. Объявления свойств и методы все определены в этом файле.

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

Чтобы создать экземпляр класса Hotel мы пишем:

В Swift нет необходимости вызывать init для объектов, так как init вызывается автоматически для нас.

Наследование классов происходит по той же схеме, что и в Objective-C, двоеточие разделяет имя класса и имя его суперкласса. В следующем примере отель наследует от класса BigHotel.

Как и в Objective-C, мы используем точечную запись для доступа к свойствам объекта. Однако Swift также использует точечную нотацию для вызова методов класса и экземпляра, как вы можете видеть ниже.

Свойства

Другое отличие Objective-C состоит в том, что Swift не различает переменные экземпляра (ivars) и свойства. Переменная экземпляра — это свойство.

Объявление свойства аналогично определению переменной или константы с использованием ключевых слов var и let. Единственное отличие - это контекст, в котором они определены, то есть контекст класса.

В приведенном выше примере комнаты - это неизменное значение, константа, равная 10, а fullRooms - это переменная с начальным значением 0, которую мы можем изменить позже. Правило состоит в том, что свойства должны быть инициализированы, когда они объявлены. Единственным исключением из этого правила являются варианты, которые мы обсудим чуть позже.

Вычисленные свойства

Язык Swift также определяет вычисляемые свойства. Вычисленные свойства - это не более чем причудливые методы получения и установки, которые не хранят значения. Как видно из их названия, они вычисляются или оцениваются на лету.

Ниже приведен пример вычисляемого свойства. Для остальных примеров я изменил свойство rooms на var. Вы узнаете почему позже.

Поскольку свойство description доступно только для чтения и имеет только оператор return, мы можем опустить ключевое слово get и фигурные скобки и оставить только оператор return. Это сокращение, и это то, что я буду использовать в оставшейся части этого урока.

Мы также можем определить вычисляемые свойства чтения записи. В нашем классе Hotel мы хотим иметь свойство emptyRooms, (пустые комнаты) которое получает количество пустых комнат в отеле, но мы также хотим обновить fullRooms, (занятые комнаты) когда мы устанавливаем вычисляемое свойство emptyRooms. Мы можем сделать это, используя ключевое слово set, как показано ниже.

В установщике emptyRooms константа newValue  (новое значение) передается нам и представляет значение, переданное установщику. Важно также отметить, что вычисляемые свойства всегда объявляются как переменные, с помощью ключевого слова var, потому что их вычисленное значение можно изменить.

Методы

Мы уже рассмотрели функции ранее в этой статье. Методы - это не что иное, как функции, связанные с типом, таким как класс. В следующем примере мы реализуем метод экземпляра bookNumberOfRooms в классе Hotel, который мы создали ранее.

Инициализаторы объектов

По умолчанию инициализатор для классов является init. В функции init мы устанавливаем начальные значения экземпляра, который создается.

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

Инициализаторы также могут принимать параметры. В следующем примере показано, как это работает.

Переопределяющие методы и вычисляемые свойства

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

Результатом является то, что описание возвращает результат метода описания суперкласса со строкой "Привет!" добавлен к нему.

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

Я не знаю, сколько раз опечатка в переопределенном методе в Objective-C заставляла меня ругаться, потому что код не работал. В Swift компилятор скажет вам точно, что не так в этих ситуациях.

Структуры

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

Все, что вы можете сделать с классом, вы можете сделать со структурой, с двумя важными отличиями:

  • структуры не поддерживают наследование, как классы
  • структуры передаются по значению, а классы передаются по ссылке

Вот несколько примеров структур в Swift:

4. Варианты

Решение проблемы

Опционные опции - это новая концепция, если вы пришли из Objective-C. Они решают проблему, с которой мы все сталкиваемся как программисты. Когда мы обращаемся к переменной, в значении которой мы не уверены, мы обычно возвращаем индикатор, известный как часовой, чтобы указать, что возвращаемое значение является нулевым значением. Позвольте мне проиллюстрировать это на примере цель-C:

В приведенном выше примере мы пытаемся найти позицию @ "B" в someString. Если найден @ "B", его местоположение или положение сохраняется в pos. Но что произойдет, если @ "B" не найден в someString?

В документации говорится, что rangeOfString: возвращает NSRange с местоположением, установленным в константу NSNotFound. В случае rangeOfString: сторожем является NSNotFound. Часовые используются для указания того, что возвращаемое значение недопустимо.

В Какао есть много применений этой концепции, но значение часового отличается от контекста к контексту, 0, -1, NULL, NSIntegerMax, INT_MAX, Nil и т. д. Проблема для программиста заключается в том, что она должна помнить, какой страж используется в каком контексте. Если программист не внимателен, он может ошибочно принять действительное значение для сторожа и наоборот. Swift решает эту проблему с опциями. По словам ,  Brian Lanier «Факультет - это тот, кто правит ими всеми».

Необязательные параметры имеют два состояния: (nil)нулевое состояние, что означает, что необязательное значение не содержит значения, и второе состояние, что означает, что оно содержит действительное значение. Think of optionals as a package with an indicator to tell you if the package's contents is valid or not.

Использование

Все типы в Swift могут стать опциональными. Мы определяем необязательный, добавив? после объявления типа вот так:

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

Помните, что дополнительные функции похожи на пакеты. Когда мы объявили let someInt: Int?, Мы определили пустое поле со значением nil. Присваивая значение 10 необязательному, поле содержит целое число, равное 10, и его индикатор или состояние становится не равным нулю.

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

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

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

5. Управление памятью

Если вы помните, еще во времена ARC мы использовали сильные и слабые ключевые слова для определения принадлежности объекта. У Swift также есть сильная и слабая модель собственности, но она также вводит новую, неизвестную. Let's take a look at each object ownership model in Swift.

сильный

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

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

слабый

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

Есть одно но, однако. В Swift слабые ссылки всегда должны быть переменными с необязательным типом, потому что они имеют значение nil, когда ссылочный объект освобожден. Слабое ключевое слово используется для объявления переменной как слабой:

неизвестные 

Неизвестные ссылки являются новыми для программистов Objective-C. Неизвестная ссылка означает, что мы не несем ответственности за поддержание ссылочного объекта живым, как слабые ссылки.

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

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

Заключение

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

Я настоятельно рекомендую язык программирования Swift, который можно бесплатно приобрести в магазине Apple iBooks.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.