Статьи

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

На WWDC 2014 Apple представила одно из крупнейших обновлений для iOS с 2008 года с точки зрения разработчика. Они представили HomeKit, HealthKit, CloudKit и Extensions, и это лишь некоторые из них. Но самым большим сюрпризом на WWDC 2014 стало появление совершенно нового языка программирования Swift.

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

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

Чтобы лучше понять Swift, Apple за последние несколько лет предоставила нам структурные улучшения Objective-C. Улучшения Objective-C, такие как блоки кода, буквенные массивы и определения словарей, а также ARC (автоматический подсчет ссылок) — это всего лишь несколько вещей, добавленных Apple в Objective-C, которые облегчают переход на Swift.

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

Еще одна важная составляющая — это полнота отрасли. Все условные ветви, будь то if или switch/case , должны охватывать все условия. Таким образом, ни один код не может провалиться без его покрытия. Пропущенное условие в вашем выражении ветвления будет поймано и сгенерирует ошибку времени компиляции

Последний элемент философии Свифта — это его предпочтение постоянным, а не переменным. Swift определяет переменные и константы следующим образом:

1
2
let someConstant : String = «This is a constant»
var someVariable : String = «This is a variable»

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

Теперь в Swift есть гораздо больше, чем несколько улучшений синтаксиса и форматирования. Swift был построен с нуля, чтобы исправить многие распространенные C / C ++ и по своей природе Objective-C источники сбоев. Такие вопросы, как:

  • Внешние индексы в массивах
  • неинициализированные данные
  • непроверенные типы возврата
  • непроверенный доступ к указателю
  • неявный провал
  • Перейти к ошибкам

Как человек, который программирует как для iOS, так и для Android, я из первых рук знаю, насколько интереснее программирование для платформы iOS с Cocoa и UIKit. Эта серия покажет вам, насколько веселее может быть кодирование, добавив в микс Swift.

В Objective-C у нас есть заголовочные файлы ( .h ) и файлы реализации ( .m ). Это то, что Objective-C унаследовал от языка C.

В Swift класс определяется в одном файле реализации ( .swift ), который включает в себя все определения и реализации класса. Это напоминает другие языки, такие как Java и C #.

#IFNDEF необходимость в жонглировании заголовочных файлов и добавлении надоедливого #IFNDEF вверху заголовочных файлов.

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

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

Другое важное изменение в Swift заключается в том, что фигурные скобки обязательны для операторов if . Это означает, что больше нет ошибок Heartbleed .

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

Начну с того, что покажу три фрагмента кода, которые иллюстрируют некоторые сходства с Objective-C. Это поможет вам в понимании языка Swift.

1
2
3
4
5
6
7
8
9
// Objective-C
for (int index = 0; index < 5; i++) {
     NSLog(@»%d»,index);
}
 
// Swift
for index in 1..<5 {
    plrintln(«\(index)»);
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
// Objective-C
switch(index) {
    case 0:
        break;
    case 1:
        break;
    default:
        break;
}
 
// Swift
switch(index) {
    case 0:
     
    case 1:
 
    default:
}
 
// no break statement
01
02
03
04
05
06
07
08
09
10
11
12
// Objective-C
if (index == 0) {
 
}
 
// Swift
if index == 0 {
 
}
 
// parentheses are optional
// curly braces are required

Программисты Objective-C обнаружат, что Swift имеет те же операторы ветвления и итерации, с которыми вы уже знакомы, такие как if/else , for циклов, для … for..in циклов и операторов switch .

Swift включает в себя два оператора диапазона, ..< и ... , для указания диапазона значений. В приведенном выше цикле for мы используем оператор полузакрытого диапазона , ..< , чтобы указать диапазон значений, который включает 1, 2, 3 и 4, но исключает 5. Другой оператор диапазона — это оператор закрытого диапазона ... Он определяет диапазон значений, который включает значение по обе стороны от оператора закрытого диапазона. Например, 1...5 . задает диапазон значений от 1 до 5, включая 5.

Давайте вернемся к примеру, который я показал вам ранее.

1
2
let someConstant : String = «This is a constant»;
var someVariable : String = «This is a variable»;

В Swift мы определяем константы, используя ключевое слово let а переменные — ключевое слово var . Двоеточие, : , является маркером для определения типов. В приведенном выше примере мы создаем константу и переменную типа String .

Мы также инициализируем константу и переменную строкой. В Swift строки определяются так же, как строки C в Objective-C, им не предшествует символ @ .

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

Если мы переписываем приведенный выше пример, позволяющий выводу типа выполнять свою работу, то фрагмент кода выглядит следующим образом:

1
2
3
4
let someConstant = «This is a constant»;
var someVariable = «This is a variable»;
let someInt = 1;
let someFloat = 1.0;

Это намного лучше, а код намного чище. Компилятор достаточно умен, чтобы понять, что someInt является Int а someFloat является Double .

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

Давайте начнем с примера Objective-C. Чтобы объединить две строки в Objective-C, мы делаем следующее:

1
2
NSString *string = @»Hello «;
NSString *greeting = [string stringByAppendingString:@»World!»];

В Swift, чтобы добавить строку к другой строке, мы используем оператор + . Это так просто.

1
2
let string = «Hello «
let greeting = string + «World!»

Строки в Swift — это Unicode, что означает, что мы можем написать:

1
let string = «你好世界»

Мы можем перебирать символы строки, используя оператор for..in как показано в следующем примере. Мы также можем использовать цикл for..in для итерации строк Unicode. Это действительно так круто.

01
02
03
04
05
06
07
08
09
10
11
let str = «Hello»;
for char in str {
    println(char);
}
 
// outputs
// H
// e
// l
// l
// o

И последнее, что я хотел бы рассказать о строках перед тем, как продолжить, это интерполяция строк. В Objective-C, если мы хотим вывести строку с переменными, мы вызываем [NSString stringWithFormat:] . В Swift переменные могут быть встроены. Посмотрите на следующий пример.

1
2
3
4
5
6
7
let x = 4;
let y = 5;
 
println( «\(x) x \(y) = \(x*y)»)
 
// outputs
// 4 x 5 = 20

Чтобы использовать интерполяцию строк, вы заключаете вызов переменной или функции в скобки и ставите перед ним обратную косую черту, \( expression) .

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

Как вы используете коллекции в Swift? В Swift их называют Array и Dictionary . Объявление массива в Swift аналогично объявлению литерала массива в Objective-C с использованием набора квадратных скобок [ ] , но без предшествующего им символа @ .

1
2
let someArray:[String] = [«one»,»two»,»three»];
var someOtherArray:[String] = [«alpha»,»beta»,»gamma»];

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

1
2
let someDictionary:[String:Int] = [«one»:1, «two»:2, «three»:3];
var someOtherDictionary:[String:Int] = [«cats»:1, «dogs»:4, «mice»:3];

Если объект Array эквивалентен объекту NSArray объект Dictionary эквивалентен объекту NSDictionary , то как мы можем создать изменяемые массивы и словари в Swift?

Ответ очень прост, объявите объект как переменную. Другими словами, в предыдущем примере someArray является эквивалентом экземпляра someOtherArray , а someOtherArray — экземпляром NSMutableArray . Это касается и словарей. В предыдущем примере someDictionary является эквивалентом экземпляра someOtherDictionary , а someOtherDictionary — экземпляром NSMutableDictionary . Это аккуратно, верно?

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

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

Мы можем переопределить объекты Array и Dictionary мы объявили ранее, следующим образом:

1
2
3
4
let someArray = [«one»,»two»,»three»];
var someOtherArray = [«alpha»,»beta»,»gamma»];
let someDictionary = [«one»:1, «two»:2, «three»:3];
var someOtherDictionary = [«cats»:1, «dogs»:4, «mice»:3];

Компилятор проверит коллекции во время их инициализации и определит правильный тип. Другими словами, он понимает, что someArray и someOtherArray являются коллекцией объектов String а someDictionary и someOtherDictionary являются словарями с ключами типа String и значениями типа Int .

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

1
2
3
var array = [«one»,»two»,»three»];
array += «four»;
array += [«five»,»six»];

Управлять словарями так же просто.

1
2
3
var dictionary = [«cat»: 2,»dog»:4,»snake»:8];
dictionary[«lion»] = 7;
dictionary += [«bear»:1,»mouse»:6];

Ранее я упоминал, что коллекции в Swift напечатаны, но что это значит? Если мы определим коллекцию, которая содержит объекты String , вы можете добавить только объекты String в эту коллекцию. Невыполнение этого требования приведет к ошибке.

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

01
02
03
04
05
06
07
08
09
10
11
// Car class
class Car {
    var speed = 0.0
     
    func accelerate(by: Double = 1.0) -> Bool {
        speed += by;
        return true;
    }
}
 
var cars = [ Car(), Car(), Car()];

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

1
cars += Car();

Однако добавление объекта другого типа приведет к ошибке.

1
cars += «Some String»;

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

В нашем примере объект Car имеет метод accelerate . Поскольку коллекция типизирована, мы можем извлечь элемент из массива и немедленно вызвать метод объекта в одной строке кода. Нам не нужно беспокоиться о типе элемента, поскольку коллекция содержит только объекты Car .

1
cars[0].accelerate(by: 2.0);

Чтобы выполнить то же самое в Objective-C с тем же уровнем безопасности, нам нужно написать следующее:

1
2
3
4
5
id pointer = cars[0];
if([pointer isKindOfClass:[Car class]]) {
    Car* car = (Car*) pointer;
    [car accelerateBy:2.0];
}

Наконец, для итерации массива мы используем цикл for..in :

1
2
3
for car in cars {
    car.accelerate(by:2.0);
}

Чтобы перебрать словарь, мы также используем цикл for..in :

1
2
3
for (key,value) in someDictionary {
    println(«Key \(key) has value \(value)»
}

Как видите, типизированные коллекции являются мощной функцией языка Swift.

Мы уже довольно много узнали о языке Swift, и вам следует потратить время на его освоение. Я рекомендую как можно скорее загрузить Xcode 6 и начать применять то, что вы узнали в этой статье, на новой игровой площадке Xcode. особенность. Игровые площадки позволяют играть в Swift в режиме реального времени.

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