Swift: проблемы и перспективы
Второго июня 2014 года в мире Apple случилось то, чего не ожидал никто. Apple представила новый объектно-ориентированный язык программирования — Swift.Чем может привлечь Swift? В отличие от Objective-C, в котором для каждого класса необходимо создавать файлы *.h и *.m с интерфейсом и реализацией соответственно, в Swift нужно создать лишь один файл *.swift, в котором содержатся и интерфейс, и реализация. Это значит, что исходных файлов в проекте будет в 2 раза меньше, что является плюсом. Однако возникает вопрос — как же разделить свойства класса и методы на публичные и приватные? В Objective-C мы привыкли «прятать» приватные свойства и методы в *.m файлы. Сделать это в Swift на данный момент невозможно.
По заверениям Apple, такой механизм все же появится:
Источник: https://devforums.apple.com/thread/227288 (требует учетной записи разработчика).Swift имеет отличный switch-case оператор. В отличии от Objective-C, в Swift можно выполнить перечисление по строкам и с условиями:
Swift и Objective-C могут использоваться в одном проекте, т.е. выполнить переход на Swift можно плавно, старые библиотеки и классы переписывать не обязательно.Swift-модули доступны сразу во всем проекте, в то время как в Objective-C необходимо подключить файлы интерфейса (*.h), чтобы использовать их.Теперь давайте попробуем проверить, действительно ли Swift работает быстрее. Для этого создадим 2 одинаковых приложения на Objective-C и на Swift. Функционал приложения заключается в том, чтобы загрузить контроллер (UIViewController) и в его главном представлении (UIView) разместить и отобразить картинку (UIImageView). Время будем засекать с момента полной загрузки приложения до момента отображения перого контроллера. Повторим тест 10 раз (график ниже).
Как несложно заметить, приложение на Objective-C грузит контроллер быстрее, нежели Swift-приложение, к тому же время загрузки на Objective-C более стабильное.Итак, наше приложение на Objective-C в среднем загружает контроллер за 0,02556 сек., а приложение на Swift — за 0,03404 сек. Почему же так? Потому что, скорее всего, в Apple не переписывали фреймворки, в том числе UIKit, который отвечает за создание контроллеров и представлений на Swift. Вместо этого были сделаны так называемые «обертки». Проще говоря, Swift-методы для создания контроллеров, представлений и т.д. просто вызывают в свою очередь методы на Objective-C и возвращают результат. Скорее всего, в будущем ситуация изменится, в Apple тщательно поработают над оптимизацией и в будущем приложения на Swift будут работать быстрее. Но не сейчас.Теперь давайте попробуем переименовать наш класс. Нажимаем на имя класса правой кнопкой мыши, Refactor/Rename и…:
Конечно, эта проблема однозначно будет устранена, скорее всего, уже к осени, когда выйдет финальная версия Xcode 6. Но все это еще раз намекает о «сырости» Swift.Еще бывалых iOS разработчиков, которые привыкли к Objective-C, собьет с толку то, что при использовании в Objective-C блоков (Blocks) и аналогичных им в Swift замыканий (Closures) есть различия в табуляции фигурных скобок.Вот так выглядит простой блок анимации в Objective-C:
А вот так в Swift:
Почему-то в Swift принято, чтобы закрывающая фигурная скобка была на одном уровне с телом блока. Было бы вполне логично сделать вот так (внимание на фигурные скобки { }):
Еще одна очень досадная проблема Swift связана с инкрементом. Инкремент используется в основном в циклах, в качестве счетчика.
let startDate = NSDate () var j: Int64 = 0 for var i: Int64 = 0; i<=1000000000; i = i+1 { j = i j = j+1 } println("\(NSDate().timeIntervalSinceDate(startDate))") Время выполнения данного кода: 4.44419801235199 секунды.
Но если заменить i = i+1 и j = j+1 на ++i и j++ соответственно (и это более общий случай):
let startDate = NSDate () var j: Int64 = 0 for var i: Int64 = 0; i<=1000000000; i++ { j = i j++ } println("\(NSDate().timeIntervalSinceDate(startDate))") То время выполнения резко возрастает до 624.784721970558 секунд (больше 10 минут!).
Соответственно Objective-C:
NSDate *startDate = [NSDate date]; int64_t j = 0; for (int64_t i = 0; i<= 1000000000; i = i + 1) { j = i; j = j + 1 } NSLog(@"%f", [[NSDate date] timeIntervalSinceDate:startDate]); Время: 2.842506 секунды.
NSDate *startDate = [NSDate date]; int64_t j = 0; for (int64_t i = 0; i<= 1000000000; i++) { j = i; j++; } NSLog(@"%f", [[NSDate date] timeIntervalSinceDate:startDate]); Время: 2.833201 секунды.
Для чистоты эксперимента обратим внимание только на различия между использованием i++ и i = i+1 в Swift и Objective-C и по отдельности. И не будем сравнивать их между собой, потому что int64_t в Objective-C является простым типом, а вот Int64 в Swift является структурой и, само собой, будет работать медленнее, хотя другого выхода Swift не предоставляет.Кроме того, Xcode имеет в данный момент очень слабую поддержку, плохую автодоводку кода (autocompletion), и еще не в полной мере поддерживает, пожалуй, основной фреймворк для создания iOS приложений — UIKit. Что уж говорить об остальных…Таким образом, можно сделать вывод, что Swift нам представили для того, чтобы мы его учили, пока его будут дорабатывать. Скорее всего, все перечисленные проблемы будут устранены со временем, но в настоящее время использовать Swift для создания коммерческих приложений настоятельно не рекомендуется. Сейчас он годен только для обучения. Swift обязательно займет свое место, но Objective-C все же будет использоваться как основной язык еще года 2.