Swift 3.0, много шума, а что на деле?



    В начале мая на просторах интернета разработчики языка объявили, что начинают подготовку к релизу 3.0 версию языка. Разработка 3.0 идет в мастер ветке, по релизам, можно понять, что 3-го мая был релиз Swift 2.2.1. Затем туда же начали вливать изменения касательно 3-ей версии языка. 9-го мая уже появился первый developer релиз из того же мастера, который можно накатить на последний xcode через установщик из swift.org/download/#snapshots, который включается через Preferences -> Components -> Toolchains.

    Немного общей информации о будущем релизе


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

    ABI это application binary interface, грубо говоря это совместимость бинарников разных версий между собой, можно привести аналогию с привычным нам API совместимостью, когда API 1.0 совместим с 2.0, но изменения, сделанные в 3.0, уже будут несовместимы с первой версией, поэтому при использовани API 3.0 нужно будет править код (в случае с ABI не править код, а пересобирать бинарник).

    На самом деле, как оказалось для меня открытием, Swift еще никогда не имел ABI компатибили. Это говорит о том, что либа, собранная на Swift 2.0 уже не будет резолвиться с 2.2 версией языка. Коллеги из стабильных языков:



    Вот так оказывается и живем. Но свитерам сфивтерам в этом плане повезло, потому что депенденси менеджеры (cocoapods, carthage) всегда подтягивают исходники проектов, а не бинарники, поэтому проблем с ABI совместимостью как таковых нет. Но, видимо, пока стоит воздержаться от написания проприетарных либ на сфивте и выкладывать их в паблик в виде бинарников. Да, ABI обещают добавить только к Swift 4.0.

    Посмотрим на изменения в API




    Даже метод didFinishLaunching подсвечивается варнингом, так как у него поменялась сигнатура, сейчас он стал

    /// swift 3
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]? = [:]) -> Bool {}
    
    /// swift 2
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {}
    

    Варнинги должны быть легко пофикшены тулзой для миграции на Swift 3.0 в Xcode в будущем.

    Посмотрим на изменения в стандартной библиотеке Swift и в Foundation


    ErrorType поменяли на ErrorProtocol

    /// swift 3
    enum MyError: ErrorProtocol {
        case Success
        case Fail(ErrorProtocol)
    }
    
    /// swift 2
    enum MyError: ErrorType {
        case Success
        case Fail(ErrorType)
    }
    


    Изменения для Array

    /// swift 3
    sort() // сортирует сам себя
    sorted() // сортирует и возвращает новый отсортированный массив не изменяя порядок в старом
    
    /// swift 2
    sortInPlace() // сортирует сам себя
    sort() // сортирует и возвращает новый отсортированный массив не изменяя порядок в старом
    


    то есть метод sort стал мутабельным, убрали sortInPlace и добавили sorted.

    /// swift 3
    reversed()
    append(contentsOf: [T])
    insert(T, at: Int)
    joined(separator: String)
    
    /// swift 2
    reverse()
    appendContentsOf([T])
    insert(T, atIndex: Int)
    joinWithSeparator(String)
    

    Также убрали многие конструкторы и переименовали другие методы.

    Изменения для String

    /// swift 3
    "3.0".components(separatedBy: ".")
    "3.0".substring(to: 1)
    "3.0".substring(from: 1)
    "".data(using: NSUTF8StringEncoding)
    "2.0".replacingOccurrences(of: "2", with: "3")
    "".uppercased()
    "".lowercased()
    "3.0".contains(".")
    "3.".appending("0")
    ("dir1" as NSString).appendingPathComponent("dir2")
    " 3.0 ".trimmingCharacters(in: .whitespaces())
    "".write(toFile: "/..", atomically: true, encoding: NSUTF8StringEncoding)
    
    /// swift 2
    "3.0".componentsSeparatedByString(".")
    "3.0".substringToIndex(1)
    "3.0".substringFromIndex(1)
    "3.0".dataUsingEncoding(NSUTF8StringEncoding)
    "2.0".stringByReplacingOccurrencesOfString("2", withString: "3")
    "".uppercaseString
    "".lowercaseString
    "3.0".containsString(".")
    "3.0".appendContentsOf(".release")
    ("dir1" as NSString).stringByAppendingPathComponent("dir2")
    "3.0".stringByTrimmingCharactersInSet(.whitespaceCharacterSet())
    "3.0".writeToFile("/..", atomically: true, encoding: NSUTF8StringEncoding)
    


    Кейсы для enum сейчас в ловер кейсе

    /// swift 3
    UIInterfaceOrientation.portrait
    Optional.some("")
    Optional.none
    
    /// swift 2
    UIInterfaceOrientation.Portrait
    Optional.Some("")
    Optional.None
    


    Изменения в UIKit


    /// swift 3
    let vc = UIViewController()
    vc.present(some, animated: true, completion: nil)
    vc.dismiss(animated: true, completion: nil)
    vc.prepare(for: segue sender: button)
    
    UIColor.white()
    UIColor.blue()
    
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 0, y: 0))
    path.addLine(to: CGPoint(x: 100, y: 100))
    
    // добавился знак _ в начале первого параметра + сократили имя аргумента функции, из-за чего будут варниги в проекте
    func tableView(_ tableView: UITableView, numberOfSections section: Int) -> Int { return 0 }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: NSIndexPath) -> UITableViewCell { return UITableViewCell() }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: NSIndexPath) { }
    
    /// swift 2
    let vc = UIViewController()
    vc.presentViewController(some, animated: true, completion: nil)
    vc.dismissViewControllerAnimated(true, completion: nil)
    vc.prepareForSegue(segue, sender: button)
    
    UIColor.whiteColor()
    UIColor.blueColor()
    
    let path = UIBezierPath()
    path.moveToPoint(CGPoint(x: 0, y: 0))
    path.addLineToPoint(CGPoint(x: 100, y: 100))
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 0 }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { return UITableViewCell() }
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { }
    


    Еще изменения


    /// swift 3
    NSData(contentsOf: "")
    UIApplication.shared()
    NSUserDefaults.standard().set("value", forKey: "key")
    NSFileManager.default().fileExists(atPath: "/...")
    NSBundle.main()
    
    /// swift 2
    NSData(contentsOfURL: "/")
    UIApplication.sharedApplication()
    NSUserDefaults.standardUserDefaults().setObject("value", forKey: "key")
    NSFileManager.defaultManager().fileExistsAtPath("/")
    NSBundle.mainBundle()
    


    Вот так провели swiftification, в общем пострадал весь апи, а не только стандартная библиотека. Но стоит признаться, читабельность действительно стала лучше. Релиз Swift 3.0 намечен на осень. ABI compatibility запланирована в 4.0. Чего-то нового в Swift не стоит ожидать на WWDC 2016.

    Встает вопрос, так что же всё таки выбрать на новый проект? Я голосую за Swift, с ним разработка идет намного быстрее и безопаснее ввиду очень строгой типизации и рюшечек ввиде Optional и синтаксиса замыканий/лямбд. В общем:



    Полезные ссылки:

    https://swift.org/blog/
    https://www.hackingwithswift.com/swift3
    https://github.com/apple/swift-evolution
    http://www.bensnider.com/abi-compatibility-whoopdty-do-what-does-it-all-mean.html

    update

    Стоит добавить, что разработчики Swift перелопатили весь API, чтобы сделать его как и задумывалось с первых дней языка, просто поддержка совместимости с Objective-C сделала своё дело и поломала первоначальный API дизайн. Планируется, что Swift будет работать на многих платформах, включая FreeBSD, Raspberry Pi, Android, Windows. Видимо, именно в версии 3.0 решили сделать полную переработку API, придать ему более свифтовый стиль.

    Only registered users can participate in poll. Log in, please.

    try?

    • 43.1%еще для хипстеров, я подожду стабильной версии268
    • 14.8%пофик на несовместимость и дальше буду переводить на него старые objc проекты и писать новые92
    • 26.4%пофик на несовместимость, но буду использовать только в новых проектах, objc оставлю как есть164
    • 10.1%хотел бы, но бизнес не дает :(63
    • 5.6%другое, напишу в каментах35

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 40

      +2
      Пожалуй останусь на OBJ-C. Хоть и синтаксис упорот. Но по крайней мере:
      — Стабильно
      — Без «плюшек» ввиде багов с ооочень долгим компиляцией массива, в котором ты запилил еще OPTIONAL переменную…
      Ну и разумеется AppCode отвратительно работает, что очень удурчяет.

      Вообщем поживём, увидим :).
        +5
        ввиде багов с ооочень долгим компиляцией массива

        Это далеко не самый страшный баг свифта) но вернуться на обж-си я уже не могу, глаза вытекают…
        –1
        Я бы сказал, что у свифта синтаксис не менее упорот
        +4
        По моему это хорошо, что они так легко рефакторят API стандартной библиотеки без оглядки на обратную совместимость. Пока язык молодой, они могут себе это позволить без особой боли. Потом будет сложнее.
          +2
          Не факт, что будет сложнее. Я так понимаю к каждой версии выходит codemode-tool, который приводит весь старый код к новому виду. Если такое делать постоянно, но обратная совместимость имхо не так важна. Подобного не хватает в других технологиях.
            0
            Это плохо для понимания кода программистами. После такой тулзы наверняка будут проблемы с «узнаванием» своего собственного кода, особенно в старых модулях.
              +1
              Но тут должно приходить на помощь умение разбираться в чужом коде, который на самом деле изменённый ваш. Всё равно, если синтаксис языка меняется, а вы на нём постоянно пишете, так или иначе надо будет разбираться и привыкать к новому синтаксису.
            +10

            Не понятно зачем они это называют 3.0, а не 0.3.

              0
              В последнее время вообще наблюдается тенденция использовать мажорные номера версий. Возможно, какой-то психологический трюк. Наверное, людям приятнее смотреть на версию 3.0 или 3.1, чем на 0.3.11 или что-нибудь в таком роде. С быстрым ростом версии кажется, что проект быстрее развивается, а его вес в глазах сообщества растёт. :)
              При этом правило «стабилизируем API на версии 1.0» в этом случае уже не работает.
                +6

                Мне более импонирует использование semver + плюс оговорки для major == 0, чем такой популизм.


                Тот же rust пошёл по пути постепенного развития, но базовые вещи зафиксированы с версии 1.0.0. А то, что ещё не зафиксировано и развивается — недоступно в stable. Т. е. новые api в libstd и libcore появляются только после их обкатки и в финальном виде. Что, несмотря на довольно высокий темп релизов (раз в 6 недель) позволяет выдавать продуманное стабильное API

                0
                На 0.3 совсем мало бы кто перешел, а им нужно как можно больше пользователей:
                во-первых, это более массовое тестирование, а значит меньше укромных уголков для крупных дефектов;
                во-вторых, после набора определенной критической массы поддержка Obj-C может быть сильно ограничена с высвобождением средств разработки.

                Но разделяю вашу фрустрацию.
                • UFO just landed and posted this here
                    +1
                    Собственно, если перейти по вашей ссылке, то там написано следующее:

                    Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.

                    Это примерно соответствует тому, на какой стадии сейчас находиться разработка Swift, учитывая то, с какой легкостью они позволяют себе переименовывать базовые методы в стандартной библиотеке языка. Я не хочу сказать что это само по себе плохо, просто в таком случае было бы честно говорить, что текущая версия языка – 0.3.
                    • UFO just landed and posted this here
                +1
                Изменения пролоббированы авторами учебников начального уровня: Lynda, Udemy и т.д.?
                  0
                  Это говорит о том, что либа, собраная на Swift 2.0 уже не будет резолвиться с 2.2 версией языка. Коллеги из стабильных языков:

                  В C++, насколько я знаю, стандартизации ABI нет до сих пор (я знаю только про пропозал Саттера: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4028.pdf, но за его судьбой не следил). Ну и интересно узнать про языки вне платформ JVM и .NET, у которых есть стандартизованные ABI интерфейсы.

                    +1
                    В C++ общего стандарта на ABI нет, но у каждого производителя есть свой. Можно не менять поставщика компилятора и стабилизировать ABI.
                    В Swift-е же поставщик один, а стабильности всё нет :) Молодой ещё.
                    0
                    Разница серьёзнее, чем между Python2 и Python3. При этом на Python3 народ уже много лет переходить из-за этого не хочет. В основном, программы не переходят потому, что библиотеки остались на втором, а библиотеки не переходят потому, что использующие их программы остались на втором.
                    Посмотрим что тут получится. Так сказать, сравнение развития ситуации при инъекции бабла.
                      +1

                      Мне кажется, что на Swift сейчас написано гораздо меньше кода, чем на Python 2 в то время, когда появился Python 3. Скорее всего, переход на новую версию Swift будет гораздо менее болезненным, даже без "инъекции бабла".

                      +1
                      С кейсами для enum как-то неоднозначно.
                        +1
                        Одно из самых заметных отличий второго свифта от третьего это то, что сейчас нужно обязательно указывать первый агрумент функции по полному имени.

                        Swift 2:
                        func square(a:Int) -> Int { return a * a }
                        print(square(10))


                        Swift 3:
                        func square(a:Int) -> Int { return a * a }
                        print(square(a:10))

                        или
                        func square(_ a:Int) -> Int { return a * a }
                        print(square(10))


                        Переименование функций, например, из «3.0».componentsSeparatedByString(".") в «3.0».components(separatedBy: ".") могли быть следствием этого.
                          +1
                          Вот честно просто не могу себе представить, ЗАЧЕМ?
                            0
                            Видимо, для более явного именования аргументов функции, у которых есть внутреннее и внешнее имя. Единообразие, видимо, в объявлении аргументов. Если не хочешь извне указывать имя аргумента явно — в объявлении функции используешь _ и пишешь square(10)
                              0
                              Мы тут уже пообсуждали, видимо это попытка решения проблемы выбора перегруженой функции.
                              0
                              Благо, что думать в Swift не надо :) а по каждому решению есть точное описание. По этому изменению вот:
                              https://github.com/apple/swift-evolution/blob/master/proposals/0046-first-label.md
                              В данном случае речь идет о единообразии и чистоте языка. Теперь функции единообразны с инициализаторами, где требовалось указывать первый параметр обязательно, а если ты не хочешь, то надо было ставить "_". А в других функциях требовалось наоборот дважды указывать название первой переменной, чтобы мочь ее указывать в вызове. Это могло быть confusing для людей, изучающих язык. Теперь все сделано единообразно.

                              ЗЫ как человек, который «волею судеб» год писал приложение в продакшене только на Swift каждый день, скажу, что язык мне нравится. Очень дисциплинирует. Иногда, когда возвращался на 5 минут в Obj-С, глаза действительно кровоточили от синтаксиса. Также, привыкнув к Optionals, порой было страшно в Obj-C, что передам nil в какой-то метод, которые его не принимает. Но на днях прям плотненько вернулся в старый проект на Obj-C и оказалось, что это как ездить на велосипеде, руки то помнят :))) и можно писать точно также хорошо.
                                0
                                Точно не скажу с какой версии, но сейчас в языке есть дерективы nullable и nonnull для аргументов и возвращаемых значений функций. На Swift я ещё не писал, но по описанию — похоже.

                                Вообще, сейчас в язык добавили много операторов-подсказок для компилятора, вроде NS_REQUIRES_NIL_TERMINATION.
                                  0
                                  ну, они nullable и nonnull сделали как раз по больше связи для взаимодействия со Swift. Поэтому, как только это появилось в API, то не прошло мимо меня ) спасибо!
                            +1
                            Планируется, что Swift будет работать на многих платформах, включая FreeBSD, Raspberry Pi, Android, Windows.

                            Захотел тут попробовать что-то для Linux сделать на Swift — упёрся в то, что ничего для работы с сетью пока не реализовано. Когда хотят реализовать — планов не нашёл, только «not implemented yet», то есть сделать на сервере какой-то запрос к какому-то другому REST API надо какими-нибудь обёртками на, например, сишным CURL (так делают IBM). Но хочется как-то из коробки
                              0
                              Можно посмотреть на это с другой стороны. В Swift очень удобно подключаются библиотеки на C. Недавно безо всяких проблем удалось подключить OpenGL.

                              Ещё потихоньку портируют Foundation Framework из Obj C. Здесь сказано, что NSURLRequest доступен и для Swift тоже.

                              В кроссплатформенный Swift ещё перенесли не все возможности Foundation Framework, но это одна из главных целей, поставленная для Swift 3.0:
                              Our primary goal is to achieve implementation parity with Foundation on Apple platforms. This will help to enable the overall Swift 3 goal of portability.

                              Источник

                              Сейчас Foundation собирается довольно сложно, но к релизу должны поправить.
                                0
                                Здесь сказано, что NSURLRequest доступен и для Swift тоже

                                Так это документация для макоси, никаких проблем для iOS / tvOS / OX X нет, там бриджинг на все фреймворки из Objective-C из коробки.

                                В Linux то нужно опенсорсный Swift тащить и опенсорсный Foundation (тот что swift-corelibs-foundation), а там, к сожалению, написано:
                                NSURLSession and related classes are not yet implemented.
                                  0
                                  В любом случае, к выходу Swift 3, обещают реализовать всё.

                                  Возможно какая-то часть уже сделана. Файл по ссылке не обновлялся уже пять месяцев, что для проекта у которого первый коммит сделан шесть месяцев назад — значительный срок.
                                    0
                                    Будем надеяться и ждать :)
                              0
                              А если сравнивать Swift с C#, что выглядит перспективней для мобильной разработки?

                              Насколько я понимаю, по уровню и наличию синтаксических плюшек вроде лямбда-выражений/nullable-переменных языки сопоставимы. Об IDE судить не берусь. Но на C# уже можно писать и для Android, и для iOS, а Swift только на пути к этому (да и с этой самой ABI-совместимостью у .NET получше)?..
                                +5
                                Ну окей, постараемся отбросить все предрассудки и посмотрим на вещи как они есть на самом деле.
                                Если есть желание писать под все мобильные платформы (iOS, Android, и, возможно, Windows Phone) на C#, то вероятно речь идет о silver bullet в лице Xamarin. Говорить о нем можно бесконечно, при этом как хваля его, так и презирая. Объективно, чтобы создать приложение, нужно:

                                1. Какая-то IDE для проектирования интерфейса;
                                2. Знание жизненного цикла приложения на мобильной ос;
                                3. Знание нативных библиотек;

                                «Мираж» Xamarin в том, что для того чтобы написать что-то на C#, вам, хотите вы или нет, придется разобраться в пунктах 1, 2 и 3. При этом на май 2016 года ни Xamarin Studio, ни Visual Studio нет нормального дизайнера.
                                — Для iOS вам придется использовать XCode Interface Builder, так как Storyboard формируются криво, а работа с Constraints начинает утомлять неточностью;
                                — Для Android вам придется использовать Android Studio и линковать xml-файлы обратно в Xamarin Studio, так как «IntelliSense» работает не очень хорошо, а для ресурсных xml не работает вовсе. Если конечно вы не ниндзя и пишете без подсказок в коде.

                                Далее вам будет необходимо использовать стандартные функции фреймворка или даже наследоваться:
                                — Из мира iOS вас теплыми объятиями встретит именование Objective-C функций, binding'а, интересные конструкторы с указателями;
                                — Из мира Android вас повстречает обязательное наследование от Java.Lang.Object и увлекательное жонглирование интерфейсами;

                                Ну и вишенка конечно — вопросы многопоточности, работы с сетью и хранения данных. Тут вы быстро попытаетесь спрятаться в уютном .NET домике. Он будет настолько теплым, что вы начнете выстраивать в нем свою параллельную вселенную, которая действительно будет работать.

                                Потратив значительное время на изучение нативных инструментов разработки, зазубривание нативного API и библиотек, а также переиначивая их на C#-лад, вы сделаете свое первое мобильное приложение, которое будет работать как надо. И будет выглядеть как нативное.
                                Но в этот момент *гифка где Гендальф-Белый плачет на фоне Хельмовой Пади, дождавшись помощи Эомера с войском рохирримов* — вы оглянетесь и скажете «я сделал это!», но встретившись глазами со своим боевым конем Xamarin'ом проскользнет секундная неловкость, и вы скажете: «Спасибо друг, дальше я сам», и нативная разработка станет для вас не такой страшной и более привлекательной.

                                Вытерев скупую мужскую слезу с мужественной щеки и, оценив перспективы C#, понимаешь, что он имеет крайне нишевое применение в мобильной разработке. Учитывая планы Google по использованию Swift в качестве ключевого языка для Android вывод становится очевидным — доминирование Swift в мобильной разработке лишь вопрос времени. Вероятно это случится к 5 или 6 версии Swift года через два-три. И новые программисты вряд ли будут выбирать C# для этой связки.

                                Мое субъективное мнение — Swift на текущий момент слишком дорого обходится в промышленном использовании. Перепиливание проекта после каждой новой версии требует вливание человека-часов, конвертируемых в $. Тот же Xamarin стабильнее.

                                Objective-C не такой страшный как кажется на первый взгляд, и не такой «динозавр» как можно подумать. Если понимать как он работает внутри, то у него много общего с тем же C#.

                                C# отличный язык, мой любимый. И я фанат Miguel de Icaza. Но я понимаю, что доля C# в мобильной разработке даже в среднесрочной перспективе имеет форму дули. Но, тем не менее, Xamarin — это фантастическая штука, через которую я бы советовал пройти каждому C#/.NET программисту, который хочет приоткрыть для себя дивный мир мобильной разработки.
                                  0
                                  Спасибо за содержательный ответ. Давно хотел понять, в чём подводные камни сочетания C# + Xamarin. Которое, вроде бы, призвано стать панацеей для мобильной разработки, но пока явно не становится. )

                                  А насчёт
                                  «Учитывая планы Google по использованию Swift в качестве ключевого языка для Android вывод становится очевидным — доминирование Swift в мобильной разработке лишь вопрос времени. » Вероятно это случится к 5 или 6 версии Swift года через два-три."

                                  мне кажется, за 2 — 3 года и Xamarin может обзавестись стоящей обёрткой для нативных библиотек + инструментами разработки интерфейса. Впрочем, не знаю, насколько это вероятно — просто тоже нравится C#. )
                                    0
                                    за 2 — 3 года и Xamarin может обзавестись стоящей обёрткой для нативных библиотек + инструментами разработки интерфейса.

                                    К тому моменту для большинства может встать один единственный, и страшный вопрос: «а зачем, если есть Swift?»
                                    C# никуда не денется, как и Xamarin, но может стать своеобразным «шахматным клубом».

                                    А на данный момент можно расслабиться, Google от слов к делу пока не перешел. Так что сейчас Xamarin, это «Уникальное предложение… Только сейчас… Вы сможете без труда… и т.д.» :-)
                                0
                                Оставлю этот комментарий про поддержку Windows.

                                Only users with full accounts can post comments. Log in, please.