Как стать автором
Обновить

Книга «Swift. Основы разработки приложений под iOS, iPadOS и macOS. 6-е изд. дополненное и переработанное»

Время на прочтение 8 мин
Количество просмотров 17K
image Привет, Хаброжители! Язык Swift прост, понятен и отлично подойдет как новичкам, так и опытным программистам. Чтобы начать писать код, вам потребуются только эта книга, компьютер и желание учиться. Все базовые концепции программирования и основы синтаксиса объясняются доступным языком, поэтому если вы никогда раньше не занимались разработкой, то эта книга — отличный старт. Теория чередуется с практическими примерами и кодом — так вы сразу сможете связать абстрактные понятия с реальными ситуациями. В каждой главе вас ждут тесты и домашние задания, которые помогут закрепить материал.

Исправления в шестом издании
По сравнению с предыдущим изданием эта книга содержит следующие изменения и дополнения:

Формат книги изменен (теперь она больше и толще).
Учебный материал актуализирован в соответствии со Swift 5.3 и Xcode 12.
Переписаны и обновлены большинство глав в книге.
Добавлен новый материал, который ранее не входил в книгу:

  • Пример использования фреймворка SwiftUI.
  • О выборе между классами и структурами.
  • О протокол-ориентированном программировании.
  • О числовом типе данных Decimal.
  • О ключевом слове some.
  • О принципах работы ARC и хранении value type и reference type в памяти.
  • О новых методах для работы с массивами.

Добавлены разделы «Для чего это использовать», которые кратко показывают, для чего в реальных проектах могут быть использованы изученные возможности.
Наборы (set) переименованы в множества.

Обновлены графические материалы (схемы, рисунки, графики и скриншоты).

Исправлены найденные опечатки и учтены пожелания и замечания читателей по оформлению и содержанию.

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

Весь последующий материал книги разделен на шесть частей:

Часть I. Базовые возможности Swift. После знакомства со средой разработки Xcode вы изучите базовые возможности Swift. Вы узнаете, какой синтаксис имеет Swift, что такое переменные и константы, какие типы данных существуют и как всем этим пользоваться при разработке программ.

Часть II. Контейнерные типы данных. Что такое последовательности и коллекции и насколько они важны для создания ваших программ? В этой части книги вы познакомитесь с наиболее важными элементами языка программирования.

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

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

Часть V. Нетривиальные возможности Swift. В пятой части подробно описываются приемы работы с наиболее мощными и функциональными средствами Swift. Материал этой части вы будете использовать с завидной регулярностью при создании собственных приложений в будущем. Также здесь вас ждет большая практическая работа — создание первого интерактивного приложения в Xcode Playground.

Часть VI. Введение в iOS-разработку. В конце долгого и увлекательного пути изучения языка и создания простых приложений вам предстоит окунуться в мир разработки полноценных программ. Из этой части вы узнаете основы создания интерфейсов и работы программ в Xcode «под капотом». Все это в будущем позволит вам с успехом осваивать новый материал и создавать прекрасные проекты.

Инициализаторы и деинициализаторы


Инициализатор (конструктор) — это специальный метод, выполняющий подготовительные действия при создании экземпляра объектного типа данных. Инициализатор срабатывает при создании экземпляра, а при его удалении вызывается деинициализатор.

27.1. Инициализаторы


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

Назначенные инициализаторы

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

  • классы имеют пустой встроенный инициализатор init(){};
  • структуры имеют встроенный инициализатор, принимающий в качестве входных аргументов значения всех свойств.

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

Инициализаторы класса и структуры, производящие установку значений свойств, называются назначенными (designated). Вы можете разработать произвольное количество назначенных инициализаторов с отличающимся набором параметров в пределах одного объектного типа. При этом должен существовать хотя бы один назначенный инициализатор, производящий установку значений всех свойств (если они существуют), и один из назначенных инициализаторов должен обязательно вызываться при создании экземпляра. Назначенный инициализатор не может вызывать другой назначенный инициализатор, то есть использование конструкции self.init() запрещено.

Инициализаторы наследуются от суперкласса к подклассу.

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

Инициализатор может устанавливать значения констант.

Внутри инициализатора необходимо установить значения свойств класса или структуры, чтобы к концу его работы все свойства имели значения (опционалы могут соответствовать nil).

Вспомогательные инициализаторы


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

Синтаксис объявления вспомогательных инициализаторов не слишком отличается от синтаксиса назначенных.

СИНТАКСИС

convenience init(параметры) {
    // тело инициализатора
}

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

В теле инициализатора обязательно должен находиться вызов одного из назначенных инициализаторов.

Вернемся к иерархии определенных ранее классов Quadruped, Dog и NoisyDog. Давайте перепишем класс Dog таким образом, чтобы при установке он давал возможность выводить на консоль произвольный текст. Для этого создадим вспомогательный инициализатор, принимающий на входе значение для наследуемого свойства type (листинг 27.1).

class Dog: Quadruped {
   override init() {
      super.init()
      self.type = "dog"
   }
   convenience init(text: String) {
      self.init()
      print(text)
   }
   func bark() {
      print("woof")
   }
   func printName() {
      print(self.name)
   }
}
var someDog = Dog(text: "Экземпляр класса Dog создан")

В результате при создании нового экземпляра класса Dog вам будет предложено выбрать один из двух инициализаторов: init() или init(text:). Вспомогательный инициализатор вызывает назначенный и выводит текст на консоль.

Вспомогательный инициализатор может вызывать назначенный через другой вспомогательный инициализатор.

Наследование инициализаторов


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

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

Отношения между инициализаторами


В вопросах отношений между инициализаторами Swift соблюдает следующие правила:

  • Назначенный инициализатор подкласса должен вызвать назначенный инициализатор суперкласса.
  • Вспомогательный инициализатор должен вызвать назначенный инициализатор того же объектного типа.
  • Вспомогательный инициализатор в конечном счете должен вызвать назначенный инициализатор.

На рис. 27.1. представлены все три правила

image

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

Вызов любого инициализатора из изображенных должен в итоге вызывать назначенный инициализатор суперкласса (левый верхний блок).

Проваливающиеся инициализаторы


В некоторых ситуациях бывает необходимо определить объектный тип, создание экземпляра которого может закончиться неудачей, вызванной некорректным набором внешних параметров, отсутствием какого-либо внешнего ресурса или иным обстоятельством. Для этой цели служат проваливающиеся (failable) инициализаторы. Они способны возвращать nil при попытке создания экземпляра. И это их основное предназначение.

СИНТАКСИС

init?(параметры) {
   // тело инициализатора
}

Для создания проваливающегося инициализатора служит ключевое слово init? (со знаком вопроса), который говорит о том, что возвращаемый экземпляр будет опционалом или его не будет вовсе.

В теле инициализатора должно присутствовать выражение return nil.

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

Для решения данной задачи используем проваливающийся инициализатор (листинг 27.2).

Листинг 27.2

class Rectangle {
   var height: Int
   var weight: Int
   init?(height h: Int, weight w: Int) {
      self.height = h
      self.weight = w
      if !(h > 0 && w > 0) {
         return nil
     }
   }
}
var rectangle = Rectangle(height: 56, weight: -32) // возвращает nil

Инициализатор принимает и проверяет значения двух параметров. Если хотя бы одно из них меньше или равно нулю, то возвращается nil. Обратите внимание на то, что, прежде чем вернуть nil, инициализатор устанавливает значения всех хранимых свойств.

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

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

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

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

Листинг 27.3

enum TemperatureUnit {
   case Kelvin, Celsius, Fahrenheit
   init?(symbol: Character) {
      switch symbol {
   case "K":
      self = .Kelvin
   case "C":
      self = .Celsius
   case "F":
      self = .Fahrenheit
   default:
      return nil
      }
   }
}
let fahrenheitUnit = TemperatureUnit(symbol: "F")

При создании экземпляра перечисления в качестве входного параметра symbol передается значение. На основе переданного значения возвращается соответствующий член перечисления.

У перечислений, члены которых имеют значения, есть встроенный проваливающийся инициализатор init?(rawValue:). Его можно использовать без определения в коде (листинг 27.4).

Листинг 27.4

enum TemperatureUnit: Character {
   case Kelvin = "K", Celsius = "C", Fahrenheit = "F"
}
let fahrenheitUnit = TemperatureUnit(rawValue: "F")
fahrenheitUnit!.hashValue

Члены перечисления TemperatureUnit имеют значения типа Character. В этом случае вы можете вызвать встроенный проваливающийся инициализатор, который вернет член перечисления, соответствующий переданному значению.

Альтернативой инициализатору init? служит оператор init!.. Разница в них заключается лишь в том, что второй возвращает неявно извлеченный экземпляр объектного типа, поскольку для работы с ним не требуется дополнительно извлекать опциональное значение. При этом все еще может возвращаться nil.

» Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок

Для Хаброжителей скидка 25% по купону — Swift

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Теги:
Хабы:
+15
Комментарии 5
Комментарии Комментарии 5

Публикации

Информация

Сайт
piter.com
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия