Пользователь
0,0
рейтинг
23 июня 2014 в 15:15

Разработка → Swift: проблемы и перспективы

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

Чем может привлечь Swift?
В отличие от Objective-C, в котором для каждого класса необходимо создавать файлы *.h и *.m с интерфейсом и реализацией соответственно, в Swift нужно создать лишь один файл *.swift, в котором содержатся и интерфейс, и реализация. Это значит, что исходных файлов в проекте будет в 2 раза меньше, что является плюсом. Однако возникает вопрос — как же разделить свойства класса и методы на публичные и приватные? В Objective-C мы привыкли «прятать» приватные свойства и методы в *.m файлы. Сделать это в Swift на данный момент невозможно.

image

По заверениям Apple, такой механизм все же появится:

image

Источник: https://devforums.apple.com/thread/227288 (требует учетной записи разработчика).
Swift имеет отличный switch-case оператор. В отличии от Objective-C, в Swift можно выполнить перечисление по строкам и с условиями:

let vegetable = "red pepper"
switch vegetable {
case "celery":
    let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
    let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
    let vegetableComment = "Is it a spicy \(x)?"
default:
    let vegetableComment = "Everything tastes good in soup."
}


Swift и Objective-C могут использоваться в одном проекте, т.е. выполнить переход на Swift можно плавно, старые библиотеки и классы переписывать не обязательно.
Swift-модули доступны сразу во всем проекте, в то время как в Objective-C необходимо подключить файлы интерфейса (*.h), чтобы использовать их.
Теперь давайте попробуем проверить, действительно ли Swift работает быстрее. Для этого создадим 2 одинаковых приложения на Objective-C и на Swift. Функционал приложения заключается в том, чтобы загрузить контроллер (UIViewController) и в его главном представлении (UIView) разместить и отобразить картинку (UIImageView). Время будем засекать с момента полной загрузки приложения до момента отображения первого контроллера. Повторим тест 10 раз (график ниже).

image

Как несложно заметить, приложение на Objective-C грузит контроллер быстрее, нежели Swift-приложение, к тому же время загрузки на Objective-C более стабильное.
Итак, наше приложение на Objective-C в среднем загружает контроллер за 0,02556 сек., а приложение на Swift — за 0,03404 сек. Почему же так? Потому что, скорее всего, в Apple не переписывали фреймворки, в том числе UIKit, который отвечает за создание контроллеров и представлений на Swift. Вместо этого были сделаны так называемые «обертки». Проще говоря, Swift-методы для создания контроллеров, представлений и т.д. просто вызывают в свою очередь методы на Objective-C и возвращают результат. Скорее всего, в будущем ситуация изменится, в Apple тщательно поработают над оптимизацией и в будущем приложения на Swift будут работать быстрее. Но не сейчас.
Теперь давайте попробуем переименовать наш класс. Нажимаем на имя класса правой кнопкой мыши, Refactor/Rename и…:

image

Конечно, эта проблема однозначно будет устранена, скорее всего, уже к осени, когда выйдет финальная версия Xcode 6. Но все это еще раз намекает о «сырости» Swift.
Еще бывалых iOS разработчиков, которые привыкли к Objective-C, собьет с толку то, что при использовании в Objective-C блоков (Blocks) и аналогичных им в Swift замыканий (Closures) есть различия в табуляции фигурных скобок.
Вот так выглядит простой блок анимации в Objective-C:

image

А вот так в Swift:

image

Почему-то в Swift принято, чтобы закрывающая фигурная скобка была на одном уровне с телом блока. Было бы вполне логично сделать вот так (внимание на фигурные скобки { }):

image

Еще одна очень досадная проблема 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.
Андрей Макаров @dev_ninja
карма
4,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (33)

  • +3
    А почему у вас примеры кода то картинками, то текстом?

    В отличие от Objective-C, в котором для каждого класса необходимо создавать файлы *.h и *.m с интерфейсом и реализацией соответственно...
    Разве ж это необходимо? Всегда думал, что это лишь для удобства программиста и IDE — разделение между публичными и приватными свойствами и методами класса заключаются не в расширении файла, а определяются соответствующими ключевыми словами (interface, interface (), @implementation), и писать можно как хочешь, хоть весь проект в один файл с любым расширением.

    <шутка>И зачем вам нужны приватные свойства и методы? Вам что, есть что скрывать от пользователей ваших классов? </шутка>
    Для приватных методов можно использовать локальные классы и замыкания как в JavaScript :)
    • 0
      А почему у вас примеры кода то картинками, то текстом?

      Некоторые блоки кода сделаны картинкой, чтобы в точности передать стиль кода такой, каким его можно видеть в Xcode, с учетом всех отступов, табуляций, подсветки т.д. К тому же, Хабр пока не умеет подсвечивать Swift.

      Разве ж это необходимо? Всегда думал, что это лишь для удобства программиста и IDE — разделение между публичными и приватными свойствами и методами класса заключаются не в расширении файла, а определяются соответствующими ключевыми словами (interface, interface (), @implementation), и писать можно как хочешь, хоть весь проект в один файл с любым расширением.

      Вы правы, можно хоть в один файл, но «по фен-шую» необходимо разделять на *.h и *.m
      Допустим, Вы далеете фреймворк, защищенный авторскими правами, и пишите реализацию класса в хедер файле. Логично ли это?
      Поэтому, говоря о необходимости создавать файлы *.h и *.m с интерфейсом и реализацией соответственно, имеется ввиду не отсутствие возможности сделать иначе, а подразумевается, что так делать правильно.
      • 0
        Допустим, Вы далеете фреймворк, защищенный авторскими правами, и пишите реализацию класса в хедер файле. Логично ли это?
        Если вам есть что скрывать :), и вы не хотите показывать свой код программистам его использующим, то на Objective-С вы можете сделать подключаемую бинарную библиотеку, а в хедере у вас будет только описание интерфейса.

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

        Предполагаю, что аналогично вы можете сделать и бинарную библиотеку на Swift.

        По теме заявленного Эплом увеличения скорости выполнения кода Swift по сравнению с аналогичным на Obj-C: интересно, как они этого добились? Ведь Obj-C по сути — это чистый С + опять же сишный рантайм для ООП. Перенесли объекты из кучи в стек? Как-то оптимизировали работу с виртуальными функциями и от динамического связывания перешли к статическому?

        • 0
          Value-типы и девиртуализация как минимум
        • 0
          Плюс, показанные тесты скорее всего были сделаны с переписанными для Swift библиотеками. Конечно, их нет сейчас, переписанных, но для тестового стенда он вполне могут переписать (а возможно какие-то основные уже и готовы) и провести тесты с ними, для оценки производительности. (И скорее всего, это делалось закрыто в течение последних лет).
  • +3
    Написали только о проблемах, а ведь название статьи «Swift: проблемы и перспективы».
    Но эти проблемы настолько очевидны, что их можно было бы и не рассматривать. Ведь язык только появился, и IDE с компилятором еще в бете.

    В чем посыл статьи? В том, что swift еще нельзя использовать для написания продакшн кода?
    Это и так понятно для любого, кто даже попробует просто поиграться со Swift.

    Лучше бы написали о новых фичах (кортежи, дженерики, IBInspectable/IBDesignable, ...)

    Ну и тесты некорректны так как не описаны флаги компиляции (см. stackoverflow.com/questions/24101718/swift-performance-sorting-arrays)
    • 0
      Написали только о проблемах.
      Но эти проблемы настолько очевидны, что их можно было бы и не рассматривать. Ведь язык только появился, и IDE с компилятором еще в бете.

      В чем посыл статьи? В том, что swift еще нельзя использовать для написания продакшн кода?
      Это и так понятно для любого, кто даже попробует просто поиграться со Swift.

      Да, на то статья и называется «Swift: проблемы и перспективы». Мы уточнили, что большинство этих проблем носят временный характер и будут устранены. И сделали заключение о том, что переход на Swift будет длится года 2.

      Лучше бы написали о новых фичах (кортежи, дженерики, IBInspectable/IBDesignable, ...)

      Напишем, в будущем, к тому же IBInspectable/IBDesignable являются нововведениями не языка, а среды разработки Xcode и работают как с использованием Swift, так и c Objective-C.

      Ну и тесты некорректны так как не описаны флаги компиляции (см. stackoverflow.com/questions/24101718/swift-performance-sorting-arrays)

      Флаги компиляции -Ofast в обеих случаях (Objective-C и Swift). Не приведены они, потому что в части, где анализируется проблема инкремента в Swift, мы не сравниваем его с Objective-C, т.к. в первом случае мы работаем со структурой (в Swift даже Int — структура ), а во втором — с простым типом.
      А тест на скоростью загрузки контроллера не «нагромождаем» дополнительными деталями, чтобы проиллюстрировать лишь обобщенную информацию в ситуации, приближенной к реальной. В данном случае мы не гонимся за скоростью выполнения циклов, сортировок и т.д., а просто показываем в удобном для человека виде (графиком) информацию.
      Полноценное сравнение производительности вполне потянет на отдельную статью. Мы же хотели написать кратко, причем в стиле, который будет понятным даже не очень техническому человеку, например, потенциальному заказчику. И хотели показать, что на деле Swift еще сыроват, потому что уже поступают предложения от клиентов писать на Swift.
      • +2
        Мы же хотели написать кратко, причем в стиле, который будет понятным даже не очень техническому человеку, например, потенциальному заказчику

        Заказчикам объяснить очень просто.
        1. Нет стабильной среды разработки.
        2. Нет людей в достаточной степени владеющих языком.
        Две эти причины ведут к увелечению времени разработки и следовательно стоимости.

        А вы же приводите информацию о каких-то там контролерах и скорости их загрузки, каком-то int64,…
        Откуда о них должен знать не разработчик?

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

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

        Можно подумать, что вы представляете диалог с заказчиком следующим образом:
        «Дорогие заказчики, синия линия ниже зелной! Поэтому еще нельзя разрабатывать на Swift.»

        И кстати, почему это tutorial?
        • –1
          И кстати, почему это tutorial?

          По ошибке…
        • 0
          Я понял, что Вы — фанат Swift. И я тоже, в принципе, вижу в нем мощный инструмент для разработки iOS приложений. Много раз сталкивался с людьми (сейлз менеджерами, проджект менеджерами или студентами, которые только начинают путь программиста и пытаются понять с чего начать) которые думали, что все, теперь все пишут только на свифте.
          Статья рассчитана на подавляющую массу людей, которые немного знакомы с программированием или с IT в целом, но не знаю тонкостей.
          Я вижу, что Вы на Хабре 6 лет, а в IT наверное еще дольше, и имеете большой опыт! Но нельзя писать статьи только для людей такого же уровня, как и Вы. Поверьте, я был по этой ссылке, которую вы скинули, я видел эти результаты, я повторял эти тесты у себя, но я не хотел делать идентичный пост тому комментарию на stackoverflow, который был по ссылке.
          И да, график, как мне кажется, вполне дает понять, что он показывает скорость загрузки контроллера (или для не знающего человека просто «скорость загрузки чего-то») написанного на Objective-C и на Swift. Видно, что «синяя полоска ниже», значит в Objective-C это «что-то» (контроллер) пока грузится быстрее, к тому же между перезапусками она меньше варьируется, чем на Swift. И я думаю, что каждый, кто зашел на Хабр и ему показалось интересной статья на столько, что он дочитал до момента с графиком, то он понял, что я хотел показать этим графиком. И я не призываю «гнобить» Swift, я призываю его учить, но понимать, что он и Xcode пока не совершенны.
      • +2
        >> Не приведены они, потому что в части, где анализируется проблема инкремента в Swift, мы не сравниваем его с Objective-C, т.к. в первом случае мы работаем со структурой (в Swift даже Int — структура ), а во втором — с простым типом.

        Какая разница, структура это или нет? Структура — это value-тип, т.е. реально никаких дополнительных расходов на разыменование здесь нет, а представление в памяти идентично. Соответственно, вменяемый компилятор должен сгенерировать здесь тот же самый код.

        В CLR Int32 — это тоже структура, но это не мешает JIT-компилятору делать ++ на ней обычный INC.
  • +1
    Нужно было в статье еще упомянуть о С++. Ведь
    You cannot import C++ code directly into Swift. Instead, create an Objective-C or C wrapper for C++ code.

  • 0
    А чего о самой главной бочке дегтя не написали? Swift-приложения не запускаются в OS X 10.8 и ниже и iOS 6.1 и ниже. Причем в OS X они не запускаются с сообщениями, которые простой пользователь не поймет. Так что ни о каком production использовании речи быть не может еще года 3-4 минимум.
    • 0
      В настройках проекта можно выбрать iOS 6.0. А ниже и не надо.
      И представьте себе, как только выйдет релиз iOS 8 и xCode 6, в стор нельзя будет выкладывать приложения под 5-ку.
      Что просто отлично для разработчиков.

      Так что ни о каком production использовании речи быть не может еще года 3-4 минимум.

      Полная ерунда. Слимшком много классных штук в Swift.
      • 0
        Про iOS не скажу. Скажу про OS X. Можно выставить в качестве deployment target хоть 10.7. И будет даже успешно собираться. А вот работать не будет. На 10.8 такая ошибка Symbol not found: __dispatch_source_type_memorypressure.
        И какое мне дело до кучи разных классных штук, если у меня клиенты в основном сидят на 10.8, а некоторые даже на 10.7? Вывод: в production для серьезной разработки использовать нельзя, пока большая часть народа не соскочит со старых версий ОС, а это года 3-4 минимум.
        Полуофициальное заявление — twitter.com/jckarter/status/473539096065736705
  • –1
    И это язык от Apple?..
  • 0
    Ну вот сейчас тут языкосрач начнется :)

    Мне он просто нравится. Умеренно типобезопасный язык с довольно современными возможностями. То, что я хотел.

    Они допилят проблемы с доступом к переменным/методам, производительностью и совместимостью с основными библиотеками; подкрутят xcode в плане удобства. И будет конфетка, которая, глядишь и выйдет за пределы продуктов яблока.

    Уже сейчас пробую втыкать его в проекты. Кстати, его дебаг, имхо, неплох.

    • 0
      Objective C никуда же не вышел. И Свифт создан с целью хоть как-то осовременить разработку под платформы Яблока. Учитывая, что в нём нет даже такой простой вещи как модификаторы доступа, от ObjC он далеко не уйдёт. Эти два языка на слуху только из-за большой популярности мобильной платформы Яблока у разработчиков и Яблоко не даёт других инструментов для разработки.
      • 0
        Модификаторы доступа обещали к релизу осенью.

        Удивительно, конечно, как многие отказываются видеть за модификаторами доступа и исключениями настоящий потенциал языка.
        • 0
          Если вам показалось, что статья предназначена сказать, что «свифт плохой», то это не так. Он действительно мощный. Некоторые мои знакомые решили уйти из iOS разработки в другие сферы, я же буду переходить на свифт. И статья наверное даже призвана показать, что свифт не готов пока, но все проблемы вышеперечисленные обязательно решаться.
          • 0
            Это не ответ на вашу статью, скорее реакция на конкретный коммент Vladek и информационный шум вокруг Swift в целом.

            P.S. очень интересно было бы почитать, что же в Swift заставило людей уйти из iOS-разработки.
            • 0
              Думаю, на статью это не потянет, но напишу комментом. Некоторых людей Свифт отпугивает потому что на WWDC Apple заявляла, что он полностью готов, с полной поддержкой Икскодом и что работает быстрее. Но на практике пока немного иначе.
              Цитата одного знакомого:
              Почему они не сказали, что они разрабатывают новый язык разработки с крутыми плюшками, с которыми можно уже поиграться, но работы еще ведутся. А плейграунд вообще какая-то чепуха для тех, кто любит программировать методом подбора, пальцем в небо писать код пока не получится так, как нужно. Повалит теперь куча народу, для джунов учить будет просто, а «бывалым» придется отвыкать от обджектива! Больше народу — меньше рейт.
              А как быть с C/C++ либами, писать эти чертовы враперы. И вообще, все эти нововведения можно было бы вынести в Objective-C 3.0, а не писать новый язык!"
              • 0
                Автор сего опуса явно не смотрел WWDC session про playgrounds ;)
  • 0
    Расскажите пожалуйста, почему Int64 в виде структуры будет медленнее?
    • 0
      Наверняка это какие-нибудь «прелести» работы с двумя частями числа по отдельности…
      А еще хотелось бы услышать ответ на «Почему Int64 доступен только в виде структуры?».
      • 0
        В Swift все числовые типы есть структуры, чтобы средствами языка же определить все операции и дать пользователям возможность добавлять свои методы через расширения. Оверхеда в рантайме ноль.
  • 0
    А откуда инфомрация про «врапперы» для UIKit-вызовов? Насколько я знаю, Objective-C вызовы из Swift транслируются напрямую в objc_msgSend, без каких-либо промежуточных слоев.

    А чуть худшая скорость запуска приложения с нуля до отображения вьюшки вызвана как минимум необходимостью проинициализировать еще и стандартную библиотеку Swift.
    • +1
      А чуть худшая скорость запуска приложения с нуля до отображения вьюшки вызвана как минимум необходимостью проинициализировать еще и стандартную библиотеку Swift.


      Цитата из статьи:
      Время будем засекать с момента полной загрузки приложения до момента отображения первого контроллера.

      т.е. время на загрузку фреймворков, библиотек и т.д. не учитывается, засекается время загрузки контроллера
      • 0
        Ясно, был неправ. Еще бы Instruments померять для полноты картины.
        • 0
          Думаю, это можно будет сделать в будущих постах, следите за обновлениями :)
  • 0
  • 0
    Сам проводил тест свифта по сравнению с обжектив-си и ситуация ужасающая:

    image

    Коненчо это дебаг конфигурация, в релизе ситуация незначительно лучше.

    Еще лучше ситуация если ставить флаг -0fast, но тогда теряются некоторые фичи языка — например проверка переполнения переменных и границ массивов.

    Пока свифт — сырой продукт, ждем релиза 1.0 и поддержки в продакшене.

    Подробности - тут
    • +1
      Будем следить за обновлениями :) NSJSONSerialization, например, тоже работал сначала хуже аналогов, но потом обогнал все сериализаторы

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