Apple представила язык программирования Swift во время своей ежегодной конференции разработчиков в 2014 году, к большому удивлению сообщества разработчиков. Компания серьезно относится к Swift, это не эксперимент. Цель Swift — обеспечить поддержку приложений нового поколения для платформ Apple.
Предпосылки
программирование
Невозможно охватить основы программирования и изучить Swift в одной или двух статьях. Поэтому я предполагаю, что у вас уже есть опыт программирования. Ruby, PHP или JavaScript являются хорошей отправной точкой для изучения Swift. Если вы пришли из веб-разработки, у вас не должно возникнуть проблем с изучением основ Swift, прочитав следующие две статьи.
стриж
В следующих двух статьях я покажу вам возможности игровых площадок, функцию, представленную в Xcode 6. Мы также рассмотрим основы языка программирования Swift, такие как переменные, константы и типы данных, включая наборы, массивы и словари.
Вы также изучите основы классов и структур. В следующей статье мы рассмотрим замыкания, функции, протоколы и контроль доступа. Это должно дать вам достаточно понимания языка, чтобы завершить оставшуюся часть этой серии.
Objective-C
Строго говоря, C и Objective-C не требуются, если вы заинтересованы в разработке для платформы iOS. Тем не менее, большинство фреймворков, которые мы будем использовать для разработки приложений для iOS, написаны на C и Objective-C. Это означает, что я буду иногда говорить о C и Objective-C. Не волнуйтесь, я позабочусь о том, чтобы вы поняли все, что необходимо, чтобы держать вас на пути к достижению своей цели, станьте разработчиком iOS.
Xcode и Swift
На протяжении всей этой серии я буду использовать Xcode 7.1 и Swift 2.1 . Если вы используете более старую версию Xcode, имейте в виду, что вы не будете работать с Swift 2.1. Swift продолжает меняться быстрыми темпами, и синтаксис развивается с каждой итерацией языка. Поэтому я рекомендую использовать Xcode 7.1, который включает Swift 2.1.
1. Детские площадки
В 2014 году Apple представила игровые площадки в составе Xcode 6. Игровые площадки отлично подходят для изучения языка программирования Swift. На игровых площадках вы можете сосредоточиться на написанном коде, а не возиться с настройками проекта, файлами и папками.
Давайте создадим игровую площадку, чтобы начать изучать основы Swift. Запустите Xcode 7.1 и выберите New> Playground … в меню Xcode File . Игровые площадки поддерживают OS X, iOS и TVOS. Установите платформу на iOS и назовите детскую площадку Свифт в двух словах .
Сообщите Xcode, где вы хотите сохранить игровую площадку, и нажмите « Создать» . На первый взгляд игровая площадка выглядит как простой файл с расширением .playground , но на самом деле это папка с несколькими файлами. К счастью, нам не о чем беспокоиться. С игровой площадкой гораздо проще работать, чем с проектом XCode с десятками файлов и папок.
Пользовательский интерфейс детской площадки прост и понятен. Вы можете увидеть редактор кода слева и вывод справа. Xcode уже заполнил игровую площадку тремя строками кода. Первая строка должна выглядеть знакомо, если вы читали предыдущий урок.
1
|
//: Playground — noun: a place where people can play
|
Строка начинается с двух косых черт, //
, указывающих, что эта строка является комментарием и игнорируется компилятором. Комментарии, которые занимают несколько строк, начинаются с /*
и заканчиваются */
.
1
2
3
4
5
|
/*
This is a longer
comment spanning
multiple lines.
*/
|
Xcode также добавил оператор импорта для инфраструктуры UIKit. UIKit является наиболее важной основой для разработки под iOS. Он определяет строительные блоки, из которых создаются приложения для iOS. В Swift импортировать фреймворк так же просто, как использовать ключевое слово import
за которым следует имя фреймворка UIKit .
1
|
import UIKit
|
Последняя строка может напоминать некоторым из вас о JavaScript. Мы используем ключевое слово var
чтобы объявить переменную str
и присвоить ей значение "Hello, playground"
. Этот пример сразу показывает ключевую особенность Swift, вывод типа .
1
|
var str = «Hello, playground»
|
Приведенный выше пример немного вводит в заблуждение. Вы можете подумать, что Swift — это слабо типизированный язык, но ничто не может быть дальше от истины. Переменная str
имеет тип String
. Swift достаточно умен, чтобы определить тип str
, посмотрев на значение, которое мы ему присваиваем.
Следующий пример эквивалентен. В этом примере мы явно указываем тип переменной str
. Двоеточие после имени переменной может быть прочитано как есть типа .
1
|
var str: String = «Hello, playground»
|
2. Переменные и константы
Swift также определяет ключевое слово let
. Это ключевое слово используется для объявления константы. Язык программирования Swift поощряет использование констант всякий раз, когда это возможно. Если значение переменной не изменяется в течение ее времени жизни, оно должно быть константой. Как следует из названия, если константе дано значение, ее нельзя изменить. Это иллюстрируется в следующем примере.
В приведенном выше примере мы объявляем постоянное message
и присваиваем ему значение. Через несколько строк мы присваиваем новое значение константе message
. Поскольку мы пытаемся изменить значение message
, компилятор выдает ошибку. К счастью, компилятор предлагает исправить проблему, превращая константу message
в переменную.
3. Типы данных
Swift определяет широкий диапазон типов данных, но давайте рассмотрим некоторые наиболее распространенные типы данных, с которыми вы столкнетесь.
Булевы
Начнем с простого типа, Bool
. Логические значения в Swift так же просты и легки в использовании, как и в других языках. Следующий пример, вероятно, так же прост, как в Swift.
1
2
3
|
let myBool = true
var notTrue = false
notTrue = true
|
чисел
Числа представлены Int
, UInt
, Float
или Double
. Существуют и другие типы данных для хранения числовых значений, но они являются наиболее распространенными. Эти типы данных похожи на те, которые вы найдете в других языках программирования.
Поскольку Swift является строго типизированным языком, вам необходимо время от времени иметь дело с преобразованиями типов. Например, невозможно умножить Int
и Float
. Посмотрите на следующий пример, чтобы лучше понять проблему.
Сначала это может показаться серьезным недостатком языка Swift. Правда в том, что такое поведение присуще наиболее строго типизированным языкам. К счастью, решение простое, как вы можете видеть ниже.
Даже при том, что может показаться, что мы разыгрываем Float
, это не то, что происходит. Мы создаем или инициализируем Float
используя значение, хранящееся в.
Существует два способа создания переменной или константы: буквальный синтаксис и синтаксис инициализатора . Константы a
и b
были созданы с использованием буквального синтаксиса. Переменная str
мы обсуждали ранее, является еще одним примером буквального синтаксиса.
Чтобы создать Float
из значения, хранящегося в a
, мы используем синтаксис инициализатора. Мы создаем Float
, используя имя типа, Float
, за которым следуют две скобки, передавая в качестве параметра.
Струны
Мы уже встречали некоторые строки в этом уроке. Строка — это не более чем последовательность символов. Фактически, можно получить доступ к коллекции символов, как показано в примере ниже.
1
2
|
let city = «Brussels»
let chars = city.characters
|
В приведенном выше примере мы используем строковый литерал. В следующем примере показано, как использовать инициализатор типа String
. Синтаксис идентичен тому, что мы видели в одном из предыдущих примеров о преобразовании чисел и типов.
1
|
let country = String(«Belgium»)
|
Коллекции
Стандартная библиотека Swift определяет три общих типа коллекций: Array
, Dictionary
и Set
. Эти типы коллекций требуют небольшого объяснения, если вы знакомы с Objective-C или любым другим языком программирования. В некоторых языках словари известны как хеши, а массивы — как списки. Идея, однако, та же самая.
1
2
3
|
let myArray = [1, 2, 3, 4, 5]
let myDictionary = [«One»: 1, «Two»: 2, «Three»: 3]
let mySet = Set([«One», «Two», «Three», «Four», «Five»])
|
Массив и словарь инициализируются с использованием буквального синтаксиса. Поскольку тип Set
не имеет буквального синтаксиса, мы используем синтаксис инициализатора для создания константы mySet
.
Я уже упоминал, что Swift является строго типизированным языком, и это также имеет последствия для типов коллекций. Следующий пример иллюстрирует это. Начнем с создания переменной arr1
типа [Int]
. Это означает, что arr1
может содержать только значения типа Int
.
Второе и третье утверждение подтверждают это. Добавление целого числа работает нормально, но добавление строки приводит к ошибке компилятора. Компилятор пытается преобразовать "Two"
в Int
, но не может этого сделать. Результатом является ошибка.
Следующий пример сделает вещи еще более запутанными. Почему компилятор не жалуется на массив, содержащий значения разных типов? Причина может вас удивить. Константа arr2
имеет тип [AnyObject]
.
1
|
let arr2 = [1, 2, 3, «Four», «Five»]
|
Any
и AnyObject
Стандартная библиотека Swift определяет два специальных типа, Any
и AnyObject
. Тип Any
может представлять любой тип, а тип AnyObject
может представлять любой класс или структуру. Если вы запутались, то это совершенно нормально. Swift был разработан для AnyObject
типизации, и кажется, что Any
и AnyObject
подрывают безопасность типов Swift.
Причиной введения Any
и AnyObject
является прежде всего причина совместимости. Я уже упоминал, что большинство фреймворков, используемых для разработки Какао, написаны на C и Objective-C. Objective-C определяет тип id
, который представляет любой объект. Чтобы обеспечить совместную работу сред Swift и Cocoa, стандартная библиотека Swift представила типы Any
и AnyObject
. Мы узнаем больше об этом, когда начнем работать с фреймворками Cocoa.
4. Классы и структуры
Классы
Если вы знакомы с объектно-ориентированным программированием, то вы уже должны быть знакомы с классами. Занятия в Swift довольно обычные. Взгляните на следующий пример, в котором мы определяем класс Boat
с двумя свойствами: speed
и lifeboats
и метод deployLifeboats()
.
01
02
03
04
05
06
07
08
09
10
|
class Boat {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// …
}
}
|
Инициализация и изменение экземпляра класса Boat
просты, как вы можете видеть ниже. Вызов метода для экземпляра также не волшебен. Основы классов Swift легко понять. Правильно?
1
2
3
4
5
6
|
var boat = Boat()
boat.speed = 10.5
boat.lifeboats++
boat.deployLifeboats()
|
сооружения
Давайте теперь создадим структуру, которая выглядит удивительно похожей на класс Boat
и выясним, что отличает классы и структуры в Swift.
01
02
03
04
05
06
07
08
09
10
|
struct Ship {
var speed: Float = 0
var lifeboats: Int = 2
func deployLifeboats() {
// …
}
}
|
В следующем примере показано наиболее важное различие между классами и структурами Swift.
Этот пример иллюстрирует, что классы передаются по ссылке, а структуры передаются по значению. Что это обозначает? Мы инициализировали экземпляр Boat
, присвоили его boat1
и установили его свойство speed
в 11.0
. Мы назначили boat1
boat2
. Это означает, что boat2
имеет ссылку на boat1
. И boat1
и boat2
указывают на один и тот же экземпляр Boat
. В результате установка свойства speed
boat2
также изменяет свойство speed
boat1
.
Это не верно для структур. Мы повторяем те же шаги, используя структуру Ship
. Конечный результат другой. При назначении ship1
для ship2
значение ship1
копируется и сохраняется в ship2
. Это означает, что ship1
и ship2
указывают на разные объекты, разные экземпляры структуры Ship
. Это очень важная концепция для понимания, поэтому убедитесь, что вы понимаете это, прежде чем продолжить.
последствия
Вы уже познакомились с общими типами данных, определенными стандартной библиотекой Swift. В этом обсуждении я не упомянул, что каждый тип данных Swift, который мы обсуждали до сих пор, является структурой.
Например, каждый тип коллекции в Swift является структурой. Каждый тип чисел является структурой. Это важно знать и понимать, особенно если вы пришли из языка, который передает некоторые из этих типов по ссылке, например, Ruby и Objective-C.
Больше различий
Есть ряд других отличий, которые отличают классы и структуры в Swift. Классы поддерживают наследование, а структуры — нет. В следующем примере мы определяем класс Speedboat
который наследуется от класса Boat
. Класс Boat
является родительским классом или суперклассом Speedboat
.
1
2
3
4
5
6
7
8
9
|
class Speedboat: Boat {
}
var speedboat = Speedboat()
speedboat.speed = 100.0
speedboat.lifeboats = 0
speedboat.deployLifeboats()
|
Поскольку Boat
является родительским классом Speedboat
, Speedboat
наследует свойства и методы, определенные в классе Boat
. Пример иллюстрирует это. Несмотря на то что реализация класса myBoat
пуста, экземпляр myBoat
, myBoat
, имеет свойства speed
и lifeboats
а также метод deployLifeboats()
.
Более тонкое различие, разделяющее классы и структуры, — проверка типов во время выполнения. Вы можете проверить тип экземпляра класса во время выполнения, в то время как это невозможно для экземпляров структуры.
5. Необязательные
Дополнительные функции являются неотъемлемой частью языка программирования Swift. Давайте выясним, что такое дополнительные функции и почему они так важны. Переменная должна быть инициализирована перед использованием. Посмотрите на следующий пример, чтобы понять, что это значит.
1
2
3
|
var str: String
str.isEmpty
|
Если вы привыкли работать со строками на других языках программирования, вы можете быть удивлены, что компилятор выдает ошибку. Давайте посмотрим, что говорит нам эта ошибка.
Во многих языках программирования переменные имеют начальное значение по умолчанию. Например, в Objective-C строка в следующем фрагменте кода равна nil
.
1
|
NSString *newString;
|
Что является необязательным?
Swift использует опциональные возможности для инкапсуляции важной концепции: переменная или константа имеет значение или нет. Это так просто в Swift. Чтобы объявить переменную или константу необязательной, мы добавляем знак вопроса к типу переменной или константы.
1
|
var str: String?
|
Переменная str
больше не имеет тип String
. Теперь это тип необязательный String
. Это важно понимать. Следствием этого является то, что мы больше не можем напрямую взаимодействовать со значением str
. Значение безопасно хранится в необязательном параметре, и мы должны запросить необязательное значение, которое оно инкапсулирует.
Принудительная распаковка
Одним из способов доступа к значению необязательного параметра является принудительное развертывание необязательного значения. Мы можем получить доступ к значению str
, добавив !
на имя переменной.
1
2
3
4
5
|
var str: String?
str = «Test»
println(str!)
|
Важно, чтобы вы были уверены, что необязательный параметр содержит значение, когда вы его принудительно разворачиваете. Если вы принудительно распаковываете необязательный параметр, у которого нет значения, Swift выдает ошибку, и ваше приложение вылетает.
Дополнительное связывание
Существует более безопасный способ получить доступ к значению необязательно. В следующем примере показано, как мы можем безопасно получить доступ к значению, хранящемуся в str
, который имеет тип String?
,
1
2
3
4
5
6
7
|
var str: String?
if str != nil {
println(str!)
} else {
println(«str has no value»)
}
|
Сначала мы проверяем, равен ли str
nil
прежде чем печатать его содержимое. В этом примере str
не имеет значения. Это означает, что он не будет развернут случайно.
Есть более элегантный подход, известный как необязательное связывание. В следующем примере мы присваиваем значение, хранящееся в необязательном порядке, временной константе. Значение необязательного str
связано с константой strConst
и доступно в предложении if
оператора if
. Этот подход также работает для операторов while
.
1
2
3
4
5
6
7
8
9
|
var str: String?
str = «Test»
if let strConst = str {
println(strConst)
} else {
println(«str has no value»)
}
|
Что такое nil
?
Если вы пришли из такого языка, как Objective-C, то вы наверняка знаете, что такое nil
. В Objective-C nil
— указатель на объект, который не существует. Swift определяет nil
немного по-другому, и важно, чтобы вы поняли разницу.
В Swift nil
означает отсутствие значения, любое значение. В то время как nil
применим только к объектам в Objective-C, в Swift nil
может использоваться для любого типа.
Вы пропустили точку с запятой?
Вы заметили, что мы не использовали точки с запятой в примерах этого урока? В Swift нет необходимости использовать точки с запятой, потому что компилятор достаточно умен, чтобы понимать, когда заканчивается один оператор, а начинается другой. Если вы действительно пропускаете использование точек с запятой, тогда можно добавить их. Имейте в виду, однако, что руководство по языку рекомендует не использовать точки с запятой.
Вывод
Несмотря на то, что в этом учебном пособии мы только коснулись поверхности, теперь у вас есть общее представление о языке программирования Swift. В следующем уроке мы рассмотрим еще один ключевой компонент языка, замыкания и функции. Мы также обсудим протоколы и контроль доступа.
Если у вас есть какие-либо вопросы или комментарии, вы можете оставить их в комментариях ниже или обратиться ко мне в Twitter .