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

Разработка → Знакомьтесь, Swift! из песочницы

2 июня на конференции WWDC 2014 Apple представила новый объектно-ориентированный язык программирования — Swift. Я думаю, многие уже успели посмотреть, что из себя представляет этот язык (Swift — нововведения), поэтому я не буду останавливаться на нововведениях. Я предлагаю создать простенький проект на языке Swift, чтобы понять на деле основные отличия от привычного Obj-C.



Подготовка


Для начала необходимо установить Xcode 6 Beta. Скачать его можно отсюда:
https://developer.apple.com/devcenter/ios/index.action
Скачиваем, устанавливаем и открываем (проблем с установкой не должно возникнуть, beta версия ставится как отдельное приложение и на основной Xcode никак не влияет).
Создаем новый проект (Single View Application) -> вводим название проекта и не забываем выбрать язык Swift!



Структура


Обратите внимание на структуру, количество файлов теперь в 2 раза меньше, теперь нет необходимости в заголовочных файлах. Код, написанный в глобальной области используется в качестве точки входа для программы, так что больше не нужна функция main.


Вот как выглядит теперь AppDelegate:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
                            
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
}


Hello World


Изучение любого языка начинается с Hello World. Не станем нарушать традицию. Откройте AppDelegate.swift и добавьте в func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool строку:

println("Hello World") //Выводит в консоль

Запустите программу и вы увидите в консоли заветный Hello World. Вот так все просто.

Усложним


Немного усложним проект. Добавим любимый TableView.
Открываем Main.storyboard. Кстати, обратите внимание что для универсального приложения теперь по умолчанию создается не два storyboard, как было раньше, а всего лишь один. Количество симуляторов тоже увеличилось:


Находим в Object Library заветный Table View и переносим его на экран приложения. Растягиваем таблицу, чтобы она была на весь экран (необходимо, чтобы она совпадала с краями).


Дальше все делается как и раньше, нам нужно задать для таблицы dataSource и delegate. Для этого открываем Connection Inspector, от delegate тянем к объекту ViewController и аналогично для dataSource.



Во ViewController.swift нужно указать протоколы, которые нам понадобятся: UITableViewDataSource и UITableViewDelegate
Теперь это можно сделать так:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

Компилятор сразу ругнется:
Type 'ViewController' does not conform to protocol 'UITableViewDataSource'
Компилятор сообщает нам, что мы не определили функции протокола 'UITableViewDataSource'. Чтобы посмотреть какие функции нужно определить, зажмите command + кликните по протоколу.

protocol UITableViewDataSource : NSObjectProtocol {
    
    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!

Вот эти две функции и необходимо добавить в наш ViewController.swift
Первая функция должна возвращать количество строк в таблице (Int):

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
 {
        return 20
  }

А вторая функция возвращает ячейку таблицы:

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
    {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestSwiftCell")
        
        cell.text = "Habrapost \(indexPath.row)"
        cell.detailTextLabel.text = "Hi, \(indexPath.row)"
        
        return cell
    }

В первой строчке создаем ячейку. Разберем запись подробней:
let означает, что мы создаем константу, а не переменную.
let cell: UITableViewCell сообщаем, что тип этой константы будет UITableViewCell. По идее, необязательно сообщать какой тип будет у константы или переменной. Программа будет прекрасно работать и так:

let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestSwiftCell")

Но как мне кажется, лучше все-таки сообщать, Apple дает хороший пример почему:

let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

Напомню, как мы создавали ячейку в Obj-C:

UITableCell *cell =[[UITableCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyTestSwiftCell"]

Не нужен больше alloc, Swift все делает самостоятельно. Все методы, которые начинались с init были убраны, и теперь инициализация происходит в стиле Swift (т.е MyClass()). Причем инициализаторы с with тоже были преобразованы, то что шло после with — стало первым аргументом в инициализаторе Swift.

Вот эта запись мне особенно сильно понравилась:

cell.text = "Habrapost \(indexPath.row)"

В Obj-C, чтобы сделать простую операцию конкатенацию строк, нужно было изгаляться следующим образом:

cell.text = [NSString stringWithFormat:@"Habrapost %@", indexPath.row];

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

cell.detailTextLabel.textColor = UIColor.purpleColor()

В итоге, получаем


Немного о playground


Playground — это площадка, где можно поэкспериментировать, и если понравиться перенести в основной проект.
Для того, чтобы создать playgroung выберете File->New->File:



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


Подробней почитать можно здесь https://developer.apple.com/...

Заключение


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

Подробнее про Swift: The Swift Programming Language
Лилия @Helecta
карма
10,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

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

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

  • +21
    Что значит «с памятью возиться не надо»? Как будто со времен arc надо было возиться. А ведь здесь тот же arc, и можно так же легко сделать retain cycle. Так что никогда не будьте беспечны насчёт памяти.
  • –7
    Читабельность повысилась. Ощущения — как перейти от JavaScript к CoffeeScript.
    • +30
      Говорят, и производительность повысилась… как перейти с CoffeeScript на JavaScript.
      • +1
        Производительность кода или разработчика? В любом случае «повысилась», надо брать в кавычки, правда по разным причинам :).
      • +7
        Насчет производительности кода — то кажется всех немного обманули. Согласно простейшим бенчмаркам свифт в шесть раз медленнее в самом лучшем случае при включенных оптимизациях, а без оптимизаций до 46 раз медленней по сравнению с Obj-C. www.splasmata.com/?p=2798
        • 0
          Миллион иттераций цикла и аппенд строк все же не по показатель… И ожидаемо. И все равно будут писать на Swift :)
          Думаю swift — это как groovy или scala на платформе java. Лучше писать на нем какой UI и и где нет таких требований к производительности. А если нужно миллиард циклов и где-то проседает производительность то пишем пару классов на более низкоуровневом языке. Ведь можно смешивать.
        • +2
          Вообще, меня слегка удивило то, что они вообще сказали, что Swift быстрее. Obj-C — компилируемый язык, а в процессе компиляции можно делать что угодно. В конечном итоге всё равно будет генерироваться код для процессора, хоть из Obj-C, хоть из Swift.
        • 0
        • +1
          А вот это уже интересно. Хотя это и казалось очевидным, когда говорили о большей продуктивности. Но тут подумалось «мало ли, может в Apple знают, что делают.» Выходит, многое нужно проверять собственноручно, а не вслепую верить заявлениям.
          • 0
            Вот еще интересный замер скорости сортировки массива: stackoverflow.com/questions/24101718/swift-performance-sorting-arrays
            или stackoverflow.com/questions/24102609/why-swift-is-100-times-slower-than-c-in-this-image-processing-test
            Говорят -Ofast улучшает картину значительно, но swift тогда игнрориует множество потенциальных ошибок в коде, что тоже нехорошо.
            • +1
              Возможно, необходимо использовать сишные вставки для подобных операций? Вспоминается, как некогда вполне успешно использовались ассемблерные вставки в C/C++ коде. За несколько минут серча нашел пока только такой топик на SO: stackoverflow.com/questions/24004732/how-to-call-c-from-swift
              Пока создается впечатление, что swift вообще не предназначен для хоть сколько-нибудь низкоуровневых операций. В приведенных Вами ссылках проскакивал комментарий, мол, хочешь использовать сортировку — используй встроенную. Надо бы, кстати, сравнить производительность работы с NSDictionary у Objective-C и у Swift'а. Разгребусь, будем разбираться…
              П.С.: спасибо за полезные ссылочки.
      • –1
        Кофе компилируется в JS, и скорость та же как если бы писался JS сразу
        • –1
          Если бы кофе компилировался сразу в такой JS, на котором пишут вменяемые люди — вопросов не было бы. Тот, кто хоть раз «налетал» на чудеса компилятора, поймет меня… такие люди и на пушечный выстрел больше к этому чуду не подойдут. Впрочем, я слышал, некоторым нравится раскапывать подобные вещи.
          • +1
            Выглядит плохо != плохо работает. Можете показать конкретные вещи которые плохо оптимизированы в этом компиляторе? Делающие Кофе существенно медленнее?
          • +2
            Обычно в таких случаях приводят хотя бы один пример.
    • +3
      Вот уж дело привычки! По мне так JS читабельнее и удобнее. Да, чуть больше кода иногда надо писать. Зато точно уверен, как оно будет работать.
  • +1
    Я не вижу includes. Их, что, я надеюсь, больше нету? =)
    • 0
      Да, теперь — модули. Внутри модуля инклюды не нужны.
    • +2
      Нету) Остался только import для подключения фреймворков:

      import FrameworkName
      

      Импорт заголовочных файлов больше не нужен. Весь код видно во всем проекте, если он в рамках одного модуля
  • +9
    В Obj-C, чтобы сделать простую операцию конкатенацию строк, нужно было изгаляться следующим образом:

    cell.text = [NSString stringWithFormat:@"Habrapost %@", indexPath.row];
    



    Это не конкатинация, конкатинация это

    NSString *string = ...;
    string = [string stringByAppendingString:@"Hello"];
    
  • +2
    Отмечу важное свойство языка: эксепшнов нет. Без полноценного GC, впрочем, от них, в зависимости от неаккуратности программиста, может быть немалый вред в связи с утечками — но, в любом случае, эту особенность стоит иметь в виду.
    • 0
      На мой взгляд, при написании клиентских приложений лучше использовать поменьше исключений и ставить просто проверки на ошибки.
      Для iOS-разработчиков отсутствие GC не так уж и ужасно.

      P.S.: Ну и никто не запрещается отдельные куски писать на Objective-C, C, C++
      • +1
        Если вам нравится загрязнять код и вы пишете только 100-строчные конвертеры — тогда да. Любое мало-мальски сложное приложение может выбросить мириад исключений по бог знает каким причинам, причём не везде и не всегда нужно эти причины проверять.
        Скажем, если у вас сложная функция «посчитать баланс» и в ней вызывается 10 подфункций, а потом одна из них «валится», не имеет значения что там произошло — мы уже не можем посчитать баланс, поэтому ловим проблемы на уровне «посчитать баланс» и там сообщаем подробности. А теперь представьте тот суровый код, который нужно вставить как в каждую из 10 подфункций, так и в главной функции, чтобы предусмотреть ВСЕ проблемы кода!
        Без «исключений» программа превращается в неуправляемый, дырявый атавизм.
        • +1
          Optional/Either и аппликативные функторы лучше, чем исключения.
    • –1
      Каким образом исключения могли бы привести к утечкам при использовании ARC (в Swift по-умолчанию)?
      • 0
        • 0
          не успел отредактировать, правильная ссылка: clang.llvm.org/docs/AutomaticReferenceCounting.html#exceptions
        • 0
          Как интересно. Мой опыт связан в основном с Objective-C++ и я вижу отсутствие утечек связанных с возникновением исключений. А оказывается что для Objective-C++ по умолчанию включена опция "-fobjc-arc-exceptions" которая делает возможным exception-safe для ARC.
          • 0
            В Objective-C исключения должны вести исключительно к крэшу приложения, являясь индикатором ошибки программиста. В C++ же в этом смысле полная свобода и поэтому этот флаг включен по умолчанию.
            • +1
              Да, да. Я в курсе этого подхода в ObjC. Не удивительно что в Swift исключений просто нет да и миксовать Swift c С++ в одном файле нельзя.
    • 0
      Если в дополнение к имеющемуся Optional реализовать еще и Either (система типов это позволяет), исключения становятся вообще не нужны
  • +3
    Неужели это произошло… дьявольский язык уходит в прошлое? В эпоху C#, Python и Java (Scala) ObjC смотрелся как ужасный монстр, совершенно не читаемый.
    Свифт выглядит симпатично, просто и понятно, но блин… очередной язык :)))
    • +27
      image
  • +2
    Я когда-то хотел написать свой язык с блекджеком и.. До сих пор пишу на видуманом синтактисе разние программы) Я наверное сумашедший
    • +1
      Да нет, вы просто не битый всякими «я создам такое же, но лучше», программист )
      Каждый программист, в какой-то момент хочет написать свои CMS \ браузер \ язык

      Пишите. Через месяц другой отпустит )
    • 0
      Если вас что-то не устраивает в текущих языках и есть иде как это можно улучшить, то почему бы не попробовать ))
      lua, python, c, c++ Насколько я помню эти языки разрабатывались или одиночками или небольшими группами энтузиастов

      Так что удачи )
  • 0
    А программы написаные им можно будет запускать на более старых версиях ios и os x? Или ios8+ и 10.10+?
    • 0
      Только, что залила приложение на ios 7, работает нормально.
      Нашла ответ инженера, который занимается разработкой Swift:
      iOS 7, Mavericks, and later.
    • 0
      Да, можно. Важен deployment target, конечно. Но это вопрос не компилятора.
      Например, приложение WWDC написано на Swift. На iOS7 работает. За более ранние на скажу.
  • 0
    В XCode 6 в ступор поставило переработанное окошко New, в котором больше нет раздела Cocoa. Не понятно куда идти чтобы создать протоколы/категории
    • 0
      Честно говоря я и в Xcode 5 не пользовался этим. Просто добавлял новый файл и писал код.
  • 0
    Не стоит забывать, что вся эта красота ещё не вышла из беты, так что многие косяки уберут к моменту релиза
  • 0
    Кстати, если тип известен, то можно опустить имя структуры/класса:

    cell.detailTextLabel.textColor = .purpleColor()

    Правда пока так автоподстановка не работает.
  • +14
    image
  • +1
    Автодополнение работает пока очень странно…
    • 0
      По-моему, оно для всего в  XCode 6 немного странно работает
  • 0
    Столкнулся с двумя ошибками, в только что созданном проекте:
    SetAppThreadPriority: setpriority failed with error 45 Unknown class SelectorVC in Interface Builder file.
    Stackoverflow молчит. Кто нибудь знает как поправить?
  • 0
    По первым впечатлениям — язык очень компактный и достаточно удобный.
    Многие вещи находятся интуитивно при наличиии опыта в Objective-C.
    Пока что много странных глюков и некоторые вещи не работают как хотелось бы (тот же code suggestion к примеру) но бетта же, так что остается подождать.
    Начал учить и ковырять. Текущий проект буду стараться переводить сразу на Swift, потому что Apple, как правило, не презентует то, что не будет использоваться как основной инструмент, в самом ближайшем будущем.
    И спасибо за статью. Ничего сложного, но лишний мотиватор для попробовать.
  • 0
    Objective-C девелоперы устарели. Пожалуйста, относитесь к ним с уважением.
  • +1
    Для сравнения, написал одно и тоже приложение на двух языках Obj-C и Swift.
    В результате на Swift кода получилось в два раза меньше и файлов тоже в два раза меньше.
    Быстродействие не увеличилось, а возможно даже немного уменьшилось. Кстати, Swift хорошо проявляет себя при работе с Metal, там он действительно показывает скорость повыше чем Obj-C.
    И конечно, не обошлось без пары забавных моментов, основанных как раз на том, что он не ловит эксепшены.

    Например: Если взять список треков с iPod Player и периодически совершать skipToNextItem();, то при достижении границы массива, Obj-C останавливает воспроизведение, а Swift вылетает с fatal error.

    Но я уверен, что к публичному релизу все такие моменты будут исправлены ;)
    • 0
      Что-то точно исправят, однако напрягает отсутствие модификаторов доступа. Обещают конечно добавить со временем. Будем ждать.
    • 0
      Семантически исключения в Objective-C как раз должны ронять программу без вопросов, нельзя их просто глушить через try/catch
    • 0
      понятно что файлов в 2 раза — .h +.m -> .swift… но по сути за счет чего в два раза то кода меньше стало? ведь поменялся синтаксис, но все вызовы методов uikit, делегаты и тд и тп тоже самое. Реально в 2 раза?
  • 0
    Как документацию почитать?
    Предложило поставить iTunes — поставил, но нажатие кнопки «view in iTunes» к нужному результату всё равно не приводит.
    • 0
      Вот ссылка на документацию в формате html.
  • +1
    obj-c очень даже читабелен (для читабельности язык не обязан быть схож с java, c или python)… не знаю, как люди в этом языке увеличенную читабельность увидели, как по мне после obj-c просто вырви глаз… к примеру убоги эти разрывы внутри скобок (didFinishLaunchingWithOptions):
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
    намного читабельней эта строка
    — (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    • 0
      первое, за что я полюбил objc, так это за именование методов (сообщений).

      такой способ мне нравятся за то, что самодокументируют код.

      — (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
      означает [delegate application:app didFinishLaunchingWithOptions:dict]
      означает «делегату — приложение app закончило запуск с опциями dict»
      довольно читабельно, на мой взгляд.
  • +2
    Где же того опыта работы столько взять?
    image
    • 0
      Я надеюсь это кто-то пошутил. Слишком палевная дата. Только узнали — сразу понадобился.
      • 0
        Это посыл к разработчикам из Apple
    • 0
      Принимаю. Изучаю Swift уже 4 года. Прошу зарплату 1 400 000р.

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