Как работать с курсом «Developing iOS 9 Apps with Swift» в Xcode 8 с Swift 2.3 и Swift 3.

Стэнфордский курс CS193P Spring 2016  «Developing iOS 9 Apps with Swift«  читался для Xcode 7 и Swift 2.2.

До момента выхода новой версии Xcode 8, каждая версия Xcode была привязана к определенной версии языка программирования Swift. Начиная с Xcode 8 это не так. Swift 3 представляет множество изменений и значительная часть этих изменений разрушает ваш проект, написанный на Swift 2.2 в Xcode 7.

К счастью, Xcode 8 позволяет сделать определенные установки проекта для того, чтобы оставаться с Swift 2.3, который практически совпадает с версией Swift 2.2 в Xcode 7. Это делается для тех проектов, которые не готовы моментально перейти на Swift 3. И это очень мудрое решение.

Apple обеспечила автоматическую миграцию в Xcode 8 проектов, разработанных в Xcode 7. При этом вас спрашивают, какую версию Swift вы выбираете при этой автоматической миграции: Swift 2.3 или Swift 3.0.

В Xcode 8 вы можете разрабатывать приложения для iOS 8, iOS 9 и iOS 10. Эти приложения могут работать с приборами (и соответственно симуляторами) начиная с iPhone 5 и выше, iPad Air  и выше, и iPad Pro (9,7 дюйма)  и выше.

Поскольку все демонстрационные примеры в нашем курсе  «Developing iOS 9 Apps with Swift» были выполнены  с применением  Xcode 7 и Swift 2.2, то логично перевести их в Swift 2.3 в Xcode 8, что и было сделано, все они находятся в Github и работают прекрасно. Кроме того, в ваше распоряжение предоставляются решения Заданий этого курса в Swift 2.3 в Xcode 8, которые находятся на Github.

Но если вы обновились до Xcode 8 и у вас есть хоть какой-то опыт программирования, то я рекомендую начать изучать курс сразу в Swift 3, так как демонстрационные приложения претерпели очень незначительные синтаксические изменения, не затрагивающие их смысловой характер. Кроме того, в вашем распоряжении Swift 3 версия всех демонстрационных примеров, находящаяся на Github. Кроме того, в ваше распоряжение предоставляются решения Заданий этого курса в Swift 2.3 в Xcode 8, которые находятся на Github.

Давайте более подробно рассмотрим оба варианта:  оставаться ли на Swift 2.3  или сразу работать на Swift 3. А вы, на основании этой информации, сами примите решение.

Во-первых, для нашего курса нужно выставить iOS 9 в качестве Deployment Target вместо iOS 10 в General настройках проекта:

screen-shot-2016-10-04-at-6-35-30-pm

Если вы перенесли свое приложение в Xcode 8 c помощью автоматического мигратора, то Deployment Target уже выставлена в iOS 9, и вы можете спокойно продолжать работу с вашим проектом в Xcode 8 c той версией Swift, которую вы выбрали при миграции.
Естественно, в процессе прохождения обучающего курса вы захотите создать новый проект, и здесь начинается самое интересное. По умолчанию все новые проекты в Xcode 8 создаются в Swift 3 и на iOS 10. А как быть, если вам нужен новый проект для Swift 2.3 и iOS 9? Сменить iOS 10 на iOS 9 в установках проекта (закладка General) очень легко, и это показано на вышеприведенном рисунке. А как понизить версию проекта с Swift 3 до Swift 2.3?
Если же вы создаете новый проект и вам нужно, чтобы он работал с Swift 2.3, то необходима всего одна установка в настройках проекта, которая позволит вам работать с версией Swift, очень близкой к той, которая существует в Xcode 7. Это установка называется Use Legacy Swift Language Version. (использовать унаследованную версию Swift).

Просто пойдите в настройки проекта на закладку Build Settings и разместите в поисковой строке legacy swift, чтобы найти корректную установку в Build Setting, затем переключите на YES для работы с Swift 2.3 в Xcode 8.

screen-shot-2016-10-04-at-6-26-14-pm

Установка по умолчанию — No (Swift 3). Но для Swift 2.3 нужно установить в Yes (Swift 2.3).

Как только вы выполнили эту установку, то есть вернулись к версии Swift 2.3, вам нужно вернуть сгенерированный шаблоном код к Swift 2.3, для этого используйте  Xcode меню Editor -> Fix All in Scope, но будьте готовы к тому, что небольшую часть кода вам придется править вручную. В курсе «Developing iOS 9 Apps with Swift«  профессор всегда использует самый простой шаблон приложения — Single View Application, и нам придется поправить только код в AppDelegate.

При создан нового проекта ( в Swift 3), в AppDelegate шаблоном генерируется код, который необходимо совместить с версией Swift 2.3, что очень легко -используйте  Xcode меню Editor -> Fix All in Scope.

screen-shot-2016-10-06-at-3-45-15-pm

Вручную нам придется  только в методе didFinishLaunchingWithOptions изменить тип словаря [UIApplicationLaunchOptionsKey: Any] на [NSObject: AnyObject].
Swift 3 код:

screen-shot-2016-11-10-at-1-08-12-pm

Swift 2.3 код:

screen-shot-2016-10-06-at-3-38-11-pm

Итак, наш новый проект готов для использования в Swift 2.3. После этих установок вы можете продолжать использовать в Xcode 8 и Swift 2.3 материалы курса «Developing iOS 9 Apps with Swift»  в неизменном виде. А дальше начинается самое интересное.

Swift 3 — основной язык разработки приложений в Xcode 8, и в связи с этим необходимо сделать пару замечаний относительно продолжения использования  Swift 2.3. Во-первых, Swift 2.3 и Swift 3 — бинарно несовместимы, так что для кода приложения вы должны выбрать какую-то одну версию Swift. Обе версии полностью поддерживаются компилятором, SDKs и отладчиком (debugger), но другие возможности среды разработки IDE могут не работать с Swift 2.3. Например, Playgrounds в Xcode 8 работают только с Swift 3 и особенно приложение Swift Playgrounds для iPad также использует только Swift 3. Все шаблоны проектов в Xcode 8 используют Swift 3, вся документация представлена в формате, подходящим для Swift 3. Это может создать некоторые неудобства в разработке приложения на Swift 2.3, хотя Пол Хэгерти почти никогда не пользуется в своем курсе кодом шаблонов, понимая, что они могут измениться в любой момент, поэтому первое, что он делает,- это убирает код шаблона. Но все равно, когда вы создаете subclass класса UITableViewController, то вместе с этим классом вам приходят методы Table View DataSource, и они всегда приходят в Swift 3,  поэтому, если вы продолжаете работу в  Swift 2.3, то вы не почувствуете мощной поддержки среды Xcode 8, вы все время при создании новых классов будете спотыкаться о код, предоставляемой системой для Swift 3.

Давайте рассмотрим возможность прохождения курса CS193P Spring 2016  «Developing iOS 9 Apps with Swift«  в Xcode 8  сразу в  Swift 3.
Ниже я представлю основные синтаксические различия между Swift 2.3 и Swift 3, они очень существенны, но Пол Хэгерти написал код для своих демонстрационных примеров таким образом, что основное различие будет проявляться только в названиях методов. Это различие имеет строгую логику образования нового имени метода из старого, об этом будет подробно сказано ниже, и если вы будете следовать этой логике, то у ваc не будет никаких затруднений в работе с материалом курса сразу на Swift 3.
Итак, у вас есть два выбора: продолжать работать с материалами курса в Swift 2.3 или использовать сразу основной язык написания приложений в Xcode 8 — Swift 3. Последний вариант мне представляется более перспективным, так как чуть с большим усилием вы переходите сразу к новой версии Swift 3 в условиях комфортной среды IDE в Xcode 8.

Некоторые синтаксические отличия Swift 3 и Swift 2.3.

1. Все параметры функции имеют внешние имена, если вы не укажите обратное
В Swift 2.x  имена параметров метода не требовали внешнего имени (метки) для первого параметра, так как обычно имя первого параметра присоединялось к названию метода. Например:

screen-shot-2016-10-06-at-4-06-03-pm

Swift 3 делает внешние имена (метки) для всех параметров обязательными, если вы специально не укажите обратное, это означает, что нет различий между первым параметром и всеми остальными. На практике это приводит к тому, что последняя часть имени метода становится внешним именем (меткой) для первого параметра.
Давайте посмотрим, как выглядит код в Swift 2.3 по сравнению с Swift 3:

screen-shot-2016-10-06-at-4-19-44-pm

Заметьте, что теперь NSTimer называется Timer. Некоторые другие базовые типы также потнеряли  префикс «NS» твк что теперь мы используем UserDefaults, FileManager, Data, Date, URL, URLRequest, UUID, NotificationCenter и т.д.
Это методы, которые вы вызываете, но это рождает эффект «домино» для многих методов, которые вызываются системой: когда вы подсоединяетесь к такому фреймворку, как UIKit, то его функции даже в Swift 3 следуют старому правилу «нет имени у первого параметра».
Вот некоторые примеры сигнатур в Swift 2.3:

screen-shot-2016-10-06-at-6-38-58-pm

В Swift 3 все эти методы нуждаются в символе «_» подчеркивания перед первым параметром, который просигнализирует тому, кто вызывает этот метод ( системный код Objective-C), чтобы он не использовал метку для первого параметра:

screen-shot-2016-10-06-at-6-35-54-pm

2. Убираем ненужные слова в названии методов

Когда в Декабре 2015 Swift стал Open Source, он знаменовал собою появление новых методических рекомендаций по созданию API, которые содержали три судьбоносных слова «убрать ненужные слова.» И это представляет собой еще один источник значимых изменений в Swift 3, потому чьи это означает, что у методов, содержащих самоочевидные слова, эти слова убраны.
Давайте взглянем на несколько простейших примеров, сначала на Swift 2.3:

screen-shot-2016-10-06-at-7-12-05-pm

Можете вы идентифицировать ненужные слова? Когда вы работаете с UIColor, конечно:  blue предполагает цвет, так что нет необходимости писать blueColor(). Когда вы добавляете одну строку с атрибутами attributedString к другой строке с атрибутами anotherString, разве вам нужно указывать, что вы добавляете строку с атрибутами appendAttributedString, а не «слона»? И почему это должен быть метод — очевидно, что цвет должен быть свойством!
Вот тот же самый код в Swift 3:

screen-shot-2016-10-06-at-7-10-53-pm

Как вы видите, это делает названия методов значительно короче.
Эти изменения особенно действенны для строк String, которые имеют повторения  повсюду. Наилучший способ это продемонстрировать — это разместить код один под другим, чтобы показать что было ДО и ПОСЛЕ. Первая строка каждой пары соответствует Swift 2.3, а вторая — Swift 3.0:

screen-shot-2016-10-06-at-8-36-55-pm

Иногда имя метода бывает настолько коротким, что не совсем понятно, о чем идет речь. Например, посмотрите на этот код:

screen-shot-2016-10-06-at-9-24-11-pm

«А что, собственно, dismiss (убирается с экрана)?» Вы сможете это узнать, если вспомните эквивалентный код в Swift 2.3:

screen-shot-2016-10-06-at-9-22-36-pm

Фактически, второй аргумент  completion: nil является теперь необязательным, так что можно даже написать так:

screen-shot-2016-10-06-at-9-42-35-pm

То же самое касается метода prepareForSegue(), который теперь выглядит так:

screen-shot-2016-10-06-at-9-46-05-pm

3. UpperCamelCase заменен на lowerCamelCase для перечисленй  enums и свойств

Хотя синтаксически это не имеет значения, мы следуем практически строгому соглашению: classes, struct и enum используют начинающийся с Заглавной буквы «верблюжий» стиль UpperCamelCase (MyStruct, WeatherType.Cloudy), имена свойств параметров используют начинающийся с маленькой буквы «верблюжий» стиль lowerCamelCase (emailAddress, requestString).
Было употреблено сочетание «практически строгое соглашение», потому что в Swift 2.3 были исключения, которых не будет в Swift 3: свойства и параметры, начинающиеся Заглавной буквы в Swift 2.3, будут использовать стиль lowerCamelCase в Swift 3.

Иногда это выглядит немного странно: Swift 2.3 создавал NSURLRequest объекты, используя NSURLRequest (URL: someURL) – заметьте, выписанное Заглавными буквами «URL«. Swift 3 превращает это в NSURLRequest (url: someURL), а это также означает, что мы будем использовать следующий код webView.request?.url?.absoluteString для чтения URL webView.
Особенно это раздражает, когда только часть имени выписана Заглавными буквами, например, CGColor, CIColor. Да, вы угадали: они превращаются в cgColor и ciColor в Swift 3, так что теперь вы пишите такой код:

screen-shot-2016-10-07-at-5-27-59-pm

Эти изменения способствуют уверенному «вождению» : все свойства и параметры должны начинаться с маленькой буквы, исключений НЕТ.
Варианты case в перечислениях enum также изменились от стиля UpperCamelCase в Swift 2.3 к стилю lowerCamelCase для Swift 3. Это также имеет значение: перечисление enum — это тип данных (как структура struct), но значения (варианты) enum ближе к свойствам.

screen-shot-2016-10-07-at-4-12-55-pm

Вы поняли идею. Тем не менее, эти крошечные изменения внесли существенные изменения в Optional, которые, по существу, являются enum:

код Swift 2.3

screen-shot-2016-10-07-at-5-24-06-pm

Это означает, что если вы использовали .Some для работы с Optionals, вам необходимо переключиться на .some. Конечно, вы всегда можете использовать возможность полностью опустить .some – ниже два фрагмента  кода абсолютно идентичны:

screen-shot-2016-10-07-at-5-52-50-pm

4. M_PI заменяется .pi

Вот как считается периметр и площадь окружности с заданным радиусом в Swift 2.3:

screen-shot-2016-10-07-at-6-04-40-pm

В старых версиях Swift вы используете M_PI для ссылки на константу π. Swift 3 интегрирует константу π в Float, Double и CGFloat типы:
screen-shot-2016-10-07-at-6-09-16-pm
Вышеприведенный фрагмент кода с учетом вывода типа из контекста может быть переписан в Swift 3 следующим образом:

screen-shot-2016-10-07-at-6-18-30-pm

5. Core Graphics теперь выглядит более подходящим для Swift

Core Graphics — это мощный фреймворк для рисования, но он использует API C-стиля, который пугает новичков. Swift 3 вводит атрибуты для C функций, что предоставляет авторам библиотеки новые совершенно замечательные способы импортирования их кода в Swift. Например, все функции, которые начинаются с «CGContext» теперь преобразуются в методы или свойства объекта CGContext, что более характерно Swift. Да, это означает, что отвратительный нарост в виде CGContextSetFillColorWithColor (), наконец-то, становится очень привлекательным.

Давайте продемонстрируем это, вот пример в Swift 2.3:

screen-shot-2016-10-07-at-7-47-58-pm

Мы создаем frame для view, делаем расширение класса UIView, переопределяем метод drawRect() для пользовательского рисования и создаем aView с новым содержимым.
Swift 3 использует совершенно другой подход – сначала «разворачивает» текущий графический контекст context, а затем выполняет все операции по рисованию методами этого контекста context:

screen-shot-2016-10-07-at-7-57-15-pm

Примечание: Как в Swift 2.3, так и в Swift 3 графический контекст context равен nil перед тем, как view вызовет свой метод drawRect(), так что вы «разворачиваете» его либо с помощью if let конструкции, либо с помощью оператора guard, но из-за того, что Swift 3 использует вызов методов, вам необходимо развернуть его безопасно.
Такое превращение C функций существует повсюду в Swift 3, например, вы можете получить свойство numberOfPages PDF документа CGPDFDocument, также CGAffineTransform претерпела драматические изменения.
Вот несколько примеров, показывающих старый и новый синтаксис:

screen-shot-2016-10-07-at-8-13-13-pm

6. Grand Central Dispatch в Swift 3

Grand Central Dispatch (CGD) используется для операций с сетью (network), которые не блокируют пользовательский интерфейс на main queue. Он написан на C и его API представляет собой набор глобальных С функций, поэтому такая тривиальная задача, как создание асинхронной очереди и выполнение в ней какой-то задачи выглядит немного необычно в Swift 2.3:

screen-shot-2016-10-07-at-8-38-28-pm

В Swift 2.3 мы вначале выбираем dispatch_ метод  (sync или async), а затем очередь, на которую мы хотим переключить выполнение нащей задачи. Swift 3 возвращает объектно-ориентированный подход, поэтому обновленный GCD меняет этот порядок действий на обратный- вначале мы выбираем очередь queue, а затем применяем метод переключения:

screen-shot-2016-10-07-at-8-51-50-pm

Один из наиболее распространенных паттернов GCD — это выполнение некоторого задания на глобальной фоновой очереди (background queue) и  обновление пользовательского интерфейса (UI) на main queue после того, как задание выполнено. Вот как это выглядит в новом API:

screen-shot-2016-10-07-at-10-25-54-pm

Если вы использовали приоритеты очередей, то вот как они представлены в новом API для QOS случаев:

* DISPATCH_QUEUE_PRIORITY_HIGH:         .userInitiated
* DISPATCH_QUEUE_PRIORITY_DEFAULT:      .default
* DISPATCH_QUEUE_PRIORITY_LOW:          .utility
* DISPATCH_QUEUE_PRIORITY_BACKGROUND:   .background

Вот еще примеры использования нового API  GCD:

screen-shot-2016-10-07-at-10-42-06-pm

В Swift 3 dispatch_once упразднена, ее следует заменить либо глобальной, либо статической переменной или константой:

screen-shot-2016-10-07-at-10-50-22-pm

dispatch_time_t была функцией, которая переводила определенное время во время, определенное типом UInt64, который мог использоваться очередью queue. Обновленный GCD имеет более дружелюбный синтаксис для этого («прощальный привет» NSEC_PER_SEC). Вот пример использования нового API для старых dispatch_time_t вместе с dispatch_after:

screen-shot-2016-10-07-at-11-03-39-pm

Автоматическая миграция с Swift 2.3 на Swift 3.0 не умеет правильно преобразовывать параллельные очереди.

Например, обычный паттерн асинхронного выполнения на параллельной очереди QOS_CLASS_USER_INITIATED с последующим переходом на main queue  для отображения данных на UI, который на Swift 2.3 выглядит следующим образом:

screen-shot-2016-11-30-at-12-48-35-pm

 

преобразует в код с ошибкой и предлагает функцию DispatchQueue.global(priority: qos), которая будет упразднена в iOS 10:

 

screen-shot-2016-11-30-at-1-29-42-pm

Для того, чтобы убрать эту ошибку, нам нужно оставить всего одну строку:

screen-shot-2016-11-30-at-1-33-32-pm

 

7. Глаголы и Существительные в наименовании методов

Swift 3 возвращается к соглашению о наименовании методов и функций, которое было в Swift 1, то есть функции и методы именуются в зависимости от того, создают ли они «побочный эффект». И это замечательно. Давайте приведем пару примеров.

Вначале рассмотрим методы не имеющие «побочного эффекта», они, как правило, именуются Существительными. Например,

x.distance (to: y) 

array.count().

Если функции и методы имеют «побочный эффект», то они, как правило, именуются императивным Глаголом в повелительном наклонении. Если я хочу, чтобы массив X был отсортирован, то я скажу: «X отсортируй (sort) сам себя или X добавь (append) к себе Y «:

x.sort () 

x.append(y).

Таким образом Swift 3 группирует методы по двум категориям: методы, которые производят действие по месту — думайте о них как о Глаголах — и методы, которые возвращают результат выполнения определенного действия, не затрагивая исходный объект — думайте о них как о Существительных.

Давайте рассмотрим простой пример с сортировкой массива:

screen-shot-2016-10-08-at-8-43-54-am

Если НЕТ окончания «ed«, то все происходит «по месту»: sort (), reverse (), enumerate (). Это Глаголы. Каждый раз, когда Swift 3 модифицирует метод добавлением  окончания «ed»  или «ing«:  sorted ()reversed (), enumerated (), то мы имеем возвращаемое значение. Это Существительные.
Эти довольно невинные правила вызывают путаницу, если речь заходит об изменении методов сортировки при переходе от Swift 2 к Swift 3. Дело в том, что в Swift 2 все функции и методы, которые работают «по месту», содержат в своем названии слово «InPlace«, поэтому для сортировки по месту используется функция sortInPlace (), а функция sort () в Swift 2 возвращает отсортированный массив. В Swift 3, как видно из вышеприведенных примеров, sort () переименован в sorted (), а sortInPlace () в sort ().

В результате метод sort () имеет разную семантику в  Swift 2 и в Swift 3. Но это нестрашно, потому что если и в Swift 2, и в Swift 3 имеется пара функций ( как с побочным эффектом, так и без него), то миграционный «робот» блестяще осуществит замену одного имени другим.

screen-shot-2016-11-25-at-6-47-31-pm

А что, если в Swift 2 были две функции, а в Swift 3 осталась одна? Например, в Swift 2 были функции insetInPlace и insetBy, а в Swift 3 осталась, по какой-то причине, одна — insetBy? Миграционный «робот» нам в этом случае не поможет — он оставит старое название функции — insetInPlace — которое, конечно, даст ошибку, и нам придется исправлять ее вручную. 

screen-shot-2016-11-25-at-7-04-31-pm

Все методы в Swift 2 с присутствием «inPlace‘ в имени требуют особого внимания при переходе на Swift 3.

Я сама попалась на этом вроде бы невинном изменении. Рассмотрим простейший метод one(), который увеличивает размер прямоугольника bbox до тех пор, пока не «поглотит» некий другой прямоугольник rect. Этот сильно упрощенный пример имеет реальный прототип, а именно класс AxesDrawer, который был предоставлен в стэнфордском курсе для рисования осей графика в Задании 3. Именно там встречается случай, представленный ниже и с ним пришлось иметь дело при переводе класса AxesDrawer из Swift 2.3 в Swift 3.

 

screen-shot-2016-11-28-at-2-04-30-pm

В Swift 2.3  я могу использовать метод insetInPlace для прямоугольников CGRect, который будет увеличивать размер прямоугольника на dx по оси X и на dy по оси Y:

screen-shot-2016-11-21-at-7-42-13-pm

Здесь не требуется использовать возвращаемое значение метода  insetInPlace, потому что прямоугольник изменяется «по месту».

Если мы используем миграционный «робот» для перехода на Swift 3, то он оставит метод insetInPlace неизменным, так как аналога ему в Swift 3 нет, и мы получим ошибку:

screen-shot-2016-11-21-at-7-49-38-pm

В Swift 3 есть только метод insetBy, применяем его, ошибка исчезает, и нам предлагают изменить переменную var bbox на константу let bbox,

screen-shot-2016-11-21-at-7-54-48-pm

что мы и делаем:

screen-shot-2016-11-21-at-7-56-09-pm

Вы видите, что нет никаких предупреждений, никаких ошибок, а мы ведь создали «вечный» цикл, потому что новый метод  insetBy не изменяет прямоугольник «по месту», а возвращает измененное значение, которое мы не используем в цикле while, но об этом тоже почему-то нет сообщения, так что создалась ОЧЕНЬ ОПАСНАЯ ситуация, когда мы «зациклили» навсегда наш код. Надо сказать, что мне потребовался целый день, чтобы найти эту ошибку.

Мы должны присвоить возвращаемое методом insetBy значение снова bbox:

screen-shot-2016-11-21-at-9-07-15-pm

Естественно, нам предлагают обратно вернуться от константы let bbox к переменной var bbox, и мы это делаем:

screen-shot-2016-11-21-at-9-20-04-pm

Теперь код работает правильно.
Так что будьте очень внимательны с заменой методов …inPlace  при переходе на Swift 3.

8. Вы не можете сравнивать Optional значения в Swift 3

При автоматической миграции с Swift 2.3 на Swift 3.0 иногда перед некоторыми классами появляется код:

screen-shot-2016-11-19-at-8-02-26-pm

Дело в том, что до версии Swift 3 можно было сравнивать Optional значения, например, таким образом:

screen-shot-2016-11-19-at-8-19-43-pm

или так:

screen-shot-2016-11-19-at-8-17-55-pm

В Swift 3 такую возможность убрали (SE-0121 – Remove Optional Comparison Operators) и для сохранения работоспособности такого кода в Swift 3 миграционный робот добавляет вышеприведенный код, что, конечно, удобно на начальном этапе перехода на  Swift 3, но некрасиво, так как если у вас встречается сравнение  Optional значений в нескольких расположенных в отдельных файлах классах, то вышеприведенный код добавиться многократно. Этот код нужно удалить, сразу обозначится проблема и решать проблему нужно на месте, вначале избавившись от Optional с помощью синтаксической конструкции if let, а затем проведя необходимое сравнение. Например, так:

screen-shot-2016-11-19-at-8-33-21-pm

или так:

screen-shot-2016-11-19-at-8-32-30-pm

9. Swift 3 не обеспечивает автоматической совместимости (bridging) числа с NSNumber и не только.

До Swift 3 многие типы  при необходимости автоматически совмещались («bridged«) с экземплярами некоторых subclasses NSObject, например, String в NSString, или Int, Float, … в NSNumber.

В Swift 3 вам придется делать это преобразование явно (SE -0072 Fully eliminate implicit bridging conversions from Swift).

Например, в Swift 2.3 мы имели код для преобразования числа в строку:

screen-shot-2016-11-21-at-12-20-15-pm

В Swift 3 после миграционного робота мы имеем ошибку:

screen-shot-2016-11-21-at-12-23-58-pm

От нас требуют явного преобразования Double в NSNumber и мы можем использовать два способа преобразования типов — с помощью оператора as  

screen-shot-2016-11-21-at-1-04-39-pm

или с помощью инициализатора NSNumber:

screen-shot-2016-11-21-at-1-10-16-pm

Вообще надо сказать, что «кастинг» типа частично вновь вернулся в Swift 3.

10. В Swift 3 нет необходимости в «кастинге» indexPath as NSIndexPath.

В более ранних версиях (Xcode 8.0) миграционный робот вставлял «кастинг» типа indexPath as NSIndexPath.

screen-shot-2016-11-21-at-2-04-34-pm

В этом нет необходимости, это была некачественная ранняя миграция от Swift 2 к  Swift 3. Если в вашем коде покакой-то причине есть этот «кастинг», то его следует убрать:

screen-shot-2016-11-21-at-2-09-04-pm

Современный миграционный робот в Xcode 8.1 уже не делает этой ошибки.

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

В Swift 2 при вызове функции необязательно было использовать возвращаемое функцией значение,  даже если это значение не Void. Никакого предупреждения от компилятора в этом случае не поступало. Если вы хотите, чтобы пользователь получал такое предупреждение от компилятора, то вам нужно было специально разместить предложение @warn_unused_result перед декларированием этой функции. Это касалось, в основном, методов, которые меняют структуру данных. Например, sortInPlace.

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

Например, в Swift 2.3 мы могли использовать метод без получения возвращаемого значения:

screen-shot-2016-11-21-at-4-16-52-pm

Но после применения миграционного «робота» вы получите в этом коде предупреждение:

screen-shot-2016-11-21-at-4-24-44-pm

которое сообщает вам, что возвращаемое значение  [UIViewController]? не используется. Если вы хотите убрать это предупреждение, то нужно дать понять компилятору ЯВНО, что вы не интересуетесь возвращаемым значение, с помощью символа _ (подчеркивания):

screen-shot-2016-11-21-at-4-28-15-pm

ВЫВОДЫ

Стэнфордский курс CS193P Spring 2016  «Developing iOS 9 Apps with Swift»  можно вполне проходить в Xcode 8 и использовать Swift 3. Единственное отличие в  демонстрационных примерах первых 7 лекций будет в основном связано с присутствием знака «_»  подчеркивания у первого параметра в Actions, методах «жизненного цикла» и методах делегата:

screen-shot-2016-10-08-at-9-18-47-am

и с более компактными именами методов:
Код Swift 2.3

screen-shot-2016-10-08-at-6-54-10-pm

Код Swift 3

screen-shot-2016-10-08-at-6-56-42-pm

Начиная с Лекции 8, придется заменить dispatch_async методы в Swift 2.3 на объектно-ориентированную версию DispatchQueue в Swift 3:

Код Swift 2.3

screen-shot-2016-10-08-at-7-12-12-pm

Код Swift 3

screen-shot-2016-10-08-at-7-10-41-pm

Чуть сложнее ситуация с Core Data ( Лекция 10 и 11), но об этом следующий пост «Как заставить работать класс  CoreDataTableViewController в Swift 3». Так что я рекомендую проходить Стэнфордский курс CS193P Spring 2016  «Developing iOS 9 Apps with Swift«  в Xcode 8 сразу на Swift 3.