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

Разработка → Разработка iOS8 приложения на Apple Swift перевод tutorial

Статья является своеобразным продолжением статьи «Знакомьтесь, Swift!» за авторством Helecta, а также вольным переводом статьи Developing iOS Apps Using Swift Tutorial Part 2.



Итак, в первой статье мы написали простое Single View приложение, включающее таблицу с несколькими ячейками.
На этот раз мы немного углубимся и сделаем несколько более амбициозных вещей. Мы будем обращаться к API поиска iTunes, парсить ответ, полученный в JSON и отображать результаты в Table View.
На первый взгляд может показаться, что все это довольно сложно и предстоит много работы, но на самом деле это не так. Все описанное выше является достаточно простым функционалом для iOS приложений и каждый уважающий себя iOS разработчик должен это уметь.

Нам понадобится Single View Application c добавленным Table View. Останавливаться на этом не будем, так как все это достаточно просто описано в первой статье.

Подключение интерфейса


Для начала, нам нужно получить указатель на наш Table View для того чтобы использовать его в коде приложения. Отправляемся в файл ViewController.swift и сразу в инициализации класса (class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {) добавляем следующую строчку:
@IBOutlet var appsTableView : UITableView

Это позволит нам ассоциировать Table View в Storyboard с переменной «appsTableView».
Переходим к Storyboard. Кликаем по View Controller с зажатым control и тянем курсор к Table View, тем самым связывая эти объекты. В появившейся менюшке Outlets выбираем «appsTableView».


Выполнение API запроса


Теперь, после того как мы подключили интерфейс, можно выполнять наши API запросы.
В файле ViewController.swift внутри инициализации класса ViewController создаем функцию searchItunesFor(searchTerm: String).
func searchItunesFor(searchTerm: String) {
    // Для The iTunes API слова в поисковом запросе должны быть разделены при помощи "+", поэтому нам необходимо произвести соответствующие замены.
    var itunesSearchTerm = searchTerm.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
    
    // Помимо этого, необходимо удалить все что не URL-friendly
    var escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    var urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=software"
    var url: NSURL = NSURL(string: urlPath)
    var session = NSURLSession.sharedSession()
    var task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
        println("Task completed")
        if(error) {
            println(error.localizedDescription)
        }
        var err: NSError?
        var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
        if(err?) {
            println(error.localizedDescription)
        }
        var results: NSArray = jsonResult["results"] as NSArray
        dispatch_async(dispatch_get_main_queue(), {
            self.tableData = results
            self.appsTableView.reloadData()
            })
        })
    task.resume()
}


Давайте по порядку.
Исправляем наш поисковый запрос, чтобы iTunes API получил текст вида «First+Second+Third+Words» вместо «First%20Second%20…». Для этого мы используем доступный в NSString метод stringByReplacingOccurencesOfString, который заменяет пробелы на "+".
Далее, мы очищаем полученную строку от символов, которые не поддерживаются URL.
Следующие две строчки определяют объект NSURL, который будет использоваться в качестве запроса к API.
Обратим внимание на следующие две строчки:
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in

Первая берет стандартный объект NSURLSession, который используется для сетевых вызовов.
Вторая создает задание, которое и посылает запрос.
Наконец, строчка task.resume() начинает выполнение запроса.

Подготовка к получению ответа


Мы получили метод, который при вызове выполняет поиск в iTunes. Вставим его в конце метода viewDidLoad в нашем ViewController.
override func viewDidLoad() {
    super.viewDidLoad()
    searchItunesFor("Angry Birds")
}

Теперь, для того чтобы получить ответ, необходимо добавить объект, который будет хранить результаты поиска.
Поэтому, добавим инстанс NSMutableData и массив NSArray, для хранения данных для нашей таблицы (внутри инициализации класса ViewController, например сразу после указателя @IBOutlet var appsTableView: UITableView).
var data: NSMutableData = NSMutableData()
var tableData: NSArray = NSArray()

Теперь, давайте объединим функции, которые NSURLConnection будет отправлять в наш класс. Так как это делегат нашего запроса, любая информация от NSURLConnection будет возвращаться методами протокола, определенными в NSURLConnectionDataDelegate и NSURLConnectionDelegate. Поэтому, в инициализации ViewController укажем также NSURLConnectionDelegate, NSURLConnectionDataDelegate, будет что-то вроде:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSURLConnectionDelegate, NSURLConnectionDataDelegate {


Получение ответа


Нам предстоит добавить самый большую часть кода нашего приложения для обработки полученной информации.
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    self.data = NSMutableData()
}

func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
    self.data.appendData(data)
}

func connectionDidFinishLoading(connection: NSURLConnection!) {
    var err: NSError
    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options:    NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

    if jsonResult.count>0 && jsonResult["results"].count>0 {
        var results: NSArray = jsonResult["results"] as NSArray
        self.tableData = results
        self.appsTableView.reloadData()
   }
}

Когда NSURLConnection получает ответ, вызывается метод didReceiveResponse.
Тут мы просто сбрасываем наши данные, если они были, прописывая self.data = NSMutableData() для создания нового объекта.
После установки соединения, мы начинаем получать данные в методе didReceiveData. Здесь передается аргумент data: NSData, где и находится вся интересующая нас информация. Нам нужно сохранить все полученные в ответе части, поэтому мы присоединяем их к объекту self.data, созданному выше.
Наконец, после того как мы в ответе получили всю информацию, вызывается метод connectionDidFinishLoading, где мы уже можем начать использовать результат.
Мы будем использовать класс NSJSONSerialization для преобразования необработанных данных в полезную информацию в виде объектов словаря NSDictionary.
Теперь, когда мы убедились что получен какой-то ответ от iTunes, простой проверки ключа «results» будет достаточно для того чтобы удостовериться что мы получили именно то что ожидали, поэтому мы можем установить объект self.tableData равным results, а также обратиться к методу таблицы appsTableView.reloadData() для обновления ее содержимого.

Обновление интерфейса Table View UI


Для инициализации Table View в первой статье, нам необходимо было определить две функции: одна возвращает количество строк в таблице, вторая создавала ячейки и описывала их содержимое.
Обновим эти функции, в соответствии с новым функционалом.
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
    return tableData.count
}

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
    var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
    cell.text = rowData["trackName"] as String

    // Обращаемся к ключу artworkUrl60 для получения ссылки на обложку объекта
    var urlString: NSString = rowData["artworkUrl60"] as NSString
    var imgURL: NSURL = NSURL(string: urlString)

    // Скачиваем файл обложки в объект NSData для последующего отображения в ячейке
    var imgData: NSData = NSData(contentsOfURL: imgURL)
    cell.image = UIImage(data: imgData)

    // Получаем цену объекта по ключу formattedPrice и отображаем ее в качестве subtitle
    var formattedPrice: NSString = rowData["formattedPrice"] as NSString
    cell.detailTextLabel.text = formattedPrice

    return cell
}

Функция numberOfRowsInSection теперь просто возвращает количество полученных в ответе объектов.
Функция cellForRowAtIndexPath вместо отображения номера строки теперь отображает название объекта, его обложку и стоимость.

Если все хорошо и у вас получилось запустить приложение, возможно вы заметите некоторые «лаги» во время его работы. Это связано с тем, что мы не предусмотрели несколько вещей, которым уделим внимание в следующей статье.

P.S.: После выхода моего перевода, автор несколько обновил урок, немного оптимизировав код. Перевод я постарался привести в соответствие.
Переводить ли следующие статьи из этого цикла?

Проголосовало 719 человек. Воздержалось 96 человек.

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

Перевод: Jameson Quave
@amureki
карма
20,2
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

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

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

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

  • 0
    А зачем вообще нужно всё это переписывание статей под Swift? Как бы, структура кода вообще не поменялась, только язык стал читабельнее.
    • 0
      Вот и мне непонятно. Тем, кто на Obj-C программировал — работа со всем этим знакома, а остальным можно пока и на obj-c потренироваться, язык как язык, а вот все фреймворки как раз за время, пока там все стабилизируется, выучить можно.
    • +9
      Например тем, кто вообще не начинал кодить под iOS.
      • +2
        Ну да, начинать надо, разумеется, через неделю после выхода языка. И обязательно перед этим зайти на stackoverflow (ну или на другой профильный сайт) и спросить: «Я знаю JavaScript и C#, а надо ли мне учить Swift?»
        • +2
          Почему нет? От iOS разработки многих отталкивал синтаксис ObJ C (он достаточно непривычный и несколько многословный). Swift ведь для этого и сделали, чтобы таких вот разработчиков таки подключить к iOS разработке, предоставив более современный язык с улучшенным синтаксисом. Самое время начать учить сейчас, чтобы к выходу релиза уже быть готовым к профессиональной разработке.
          • –6
            не хотелось бы «таких вот разработчиков» плодить
            • +6
              Т.е. если мне привычна семантика языков, например Java, Python, С++ и Go я должен ломать мозг и перестраивать его восприятие на нечто трудно читаемое(для новичков)? Увольте, но лично мне жалко своего времени для этого. Хоть эти знания за плечами не носить, эти знания лично мне избыточны.
              А вот Swift весьма прост, относительно беглого взляда в книжку достаточно, чтобы начать писать код. И пусть это и привлечет много слабых программистов, однако это привлечет не мало и сильных, а также сделает со временем из слабых сильных, которые внесут весьма хорошую лепту в разработку фреймворков и приложений.

              • –4
                Да никто никому не должен
                Научиться ставить скобки в нужных местах сможет любой дурак, но ведь суть не в этом. А Swift кстати не так прост на самом-то деле.
                • +1
                  Дело не в скобках, а в восприятии.

                  В каждом языке дьявол кроется в деталях, поэтому тоже самое можно сказать и про Python и про Ruby, и тем более про С.
                  Важен порог входа и необходимое время на освоение базовых принципов языка.
                  • +1
                    Как говорится, писать на фортране можно на любом языке. А Swift тут имхо пока мало что меняет, от UIKit и прочих все равно не убежать. Чтобы сделать что-то большее, чем кнопка, textField и hello world в любой среде нужно потратить больше 5 минут на изучение.
              • 0
                А вы пробовали нормально программировать на Obj-C, именно сами? Он попроще С++ будет, а синтаксис — дело привычки, не более. Ничего ужасного лично я не вижу. И более того, не понимаю, раз уж люди не в состоянии программировать на Obj-C, то почему они все вдруг решили, что смогут программировать на Swift? Из-за пары лишних вызовов alloc и init? Из-за квадратных скобок?
                • –1
                  Пробовал, но не было такого 5 минут и уже пишу код. Заняло не мало времени, чтобы просто свыкнуться с синтаксисом.
                  Это было сделано лишь только для общего познания.

                  И что значит люди не в состоянии программировать на Obj-C? Если я пишу драйвера для видеокарт(к примеру просто, не пишу я их, но задачи часто сопоставимые), это значит я не в состоянии осилить Obj-C? Не нужен он просто, ну аж никак. Но иногда кое-какую UI-ку написать хочется, мне для этого надо изучать нечто кардинально новое?
                  • 0
                    Да поймите же, нет в Obj-C ничего кардинально нового, особенно для человека, знакомого с С++.
                    А по поводу изучения особенностей языка или синтаксиса — скажете, что Swift прям изучать не надо? Уж у него то особенностей скорее всего поболе, чем у Obj-C. Простота синтаксиса еще ничего не говорит о самом языке.
                    • 0
                      Я бы сказал, что сходство с плюсами только в наличии объектной модели (и та сильно разная), да и умные указатели, который в Obj-C сделаны людьми для людей, а не как в плюсах чужими для хищников.
                      Всё остальное базовое взято из старого лампового С.
                • 0
                  Я вот не пробовал долгое время из-за синтаксиса. Смотрел исходники и ужасался. Потом, таки пересилил себя и да, вы правы, язык не такой и плохой. Но если бы был swift, я бы наверное на пару лет назад начал под ios програмы писать. Хотя, он скорее, сложнее ObjC, чем проще. Просто, приятнее гораздно на первый взгляд.
                • 0
                  Всё так!
            • 0
              не хотелось бы «таких вот разработчиков» плодить
              Конкуренции боитесь? :)

              amureki: Статьи переводить! Больше статей и туториалов, хороших и разных! Что-нибудь по созданию виджетов хотелось бы почитать.
              • 0
                да нет, я хотел поиронизировать насчет самой фразы "таких вот"
            • +1
              Как раз, надо. Хотя, текущие iOS программисты могут бояться конкуренции, но в целом для отрасли я вижу следующие плюсы:

              1. Приход опытных разработчиков с других платформ: .NET, Java и т.д. Можно сколько угодно рассказывать, что хороший разработчик разберется с любым синтаксисом, но мотивация учить новый язык гораздо выше, когда он приятен со старта.

              2. Приход новичков в сферу. Можно сколько угодно рассказывать про засилье быдлокодеров, но платить разработчику большие деньги, чтобы он делал аггрегатор новостей или форму заказа для парихмахерской, неразумно. Многие заказчики просто отказываются от такой затеи. А с приходом массы неопытных разработчиков с желанием попрактиковаться, цены на простые разработки просядут и свое приложение сможет позволить себе и тот, кто раньше считал это неоправданно дорогим.
              При этом, правила appstore и то, что swift все-же не php4, позволят держать планку выше откровенного быдлокодерства. На сложные приложения новички влияния оказывать особо не будут, но избавят опытных людей от ваяния очередного приложения по простенькому шаблону.

              Пострадают только те, кто научился писать на ObjC простенькие вещи и остановился на этом, не желая развиваться. Ну и ладно, тех кто не развивается, все равно подвинули бы с рынка.
          • 0
            Соглашусь. Ходит байка, что у начинающих программистов от Objective-C начинают вытекать глаза.
            А вообще, я очень рад, что добавили Generics и перегрузку операторов. Только не понимаю, почему нельзя было реализовать перегрузку функций.
            • +1
              >почему нельзя было реализовать перегрузку функций.
              Потому что это такое же зло, как и множественное наследование?
  • +4
    А зачем так много var, хотя практически везде его можно заменить на let? У вас получается практически тупое переписывание кода ObjC.

    Да и вывод типов при присваиваниях в let работает очень читабельно и надежно (особенно при создании новых объектов):

    let imgData = NSData(contentsOfURL: imgURL)
    
    • +5
      Затем что язык только-только вышел и толпа разработчиков, которые последние 5-6 лет программировали на Objective-C и привыкли делать вещи определенным образом, полезла изучать его и выдавать статьи на-гора, используя Swift не столько как новый язык со своими подходами, сколько как большую кучу синтаксического сахара для Objective-C.

      Поэтому в ближайшие несколько месяцев (если не лет) нас ждет огромная куча статей с «плохими практиками программирования на Swift».
  • +2
    Обязательно переводить следующие статьи!
    Уже понятно, что язык обещает быть перспективным. Нужно хотя бы минимально заполнить нишу для новичков.
    Я например писал под WP, только начал изучать iOS и тут Swift выходит. Теперь хочется не просто перейти под кодинг на iOS но и начать знакомство с молодого языка.
    Буду ждать новых публикаций.
  • +1
    NSURLConnection уже давно может быть не делегатным, можно убрать эти три жутких метода connection*
    • +1
      Да и NSURLSession почти год назад появился
      • 0
        Кстати, в оригинальной публикации автор использует NSURLSession.
        • 0
          Автор несколько обновил статью, в ближайшее время я приведу перевод в порядок.
  • –1
    Перевод любых статей по Swift — дело нужное, поэтому спасибо вам за него! Но мне кажется, что переводить следующие части не стоит потому, что туториалы более эффективны в видео формате, а не в текстовом. К тому же, к ним не прилагаются исходные файлы проекта, чтобы можно было сразу открыть их в X Code 6 и поиграться.

    Намного полезнее будет потратить силы на перевод статей, объясняющих преимущества Swift перед Objective-C, поскольку некоторым может показаться, что преимущества Swift заключаются в основном только в более читабельном синтаксисе языка. В то время как Swift является мультипарадигмальным языком, поддерживающим как ООП, так и ФП! Т.е. можно сказать, что он соотносится с Objective-C, как Scala с Java.

    Заинтересовавшимся предлагаю ознакомиться с подробностями в статье "Functional Paradigms in Swift" по ссылке:
    http://blog.tackmobile.com/article/functional-paradigms-in-swift/
    • 0
      Очень правильный комментарий!
  • 0
    var err: NSError
    
    var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options:    NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
    


    Объявили переменную err и не используете её.
  • 0
    Не пойму, раньше такой шлак никто не плюсовал. Если это на Obj-c написать, что поменяется?
    И что это за говнокод?

    var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
    cell.text = rowData[«trackName»] as String

    // Обращаемся к ключу artworkUrl60 для получения ссылки на обложку объекта
    var urlString: NSString = rowData[«artworkUrl60»] as NSString

    Swift нормально типизированный чтобы не писать так. Пример кода — это Objective-C подход на языке Swift.
    Ужас один.

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