geektimes

«Программирование мышкой» в XCode 6 для Swift

  • среда, 5 ноября 2014 г. в 02:10:49
http://habrahabr.ru/post/242277/

Привет, Хабрахабр!

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

Итак, для начала для отработки примеров

Cоздадим проект SingleView Application


Если сами создавать умеете, то этот этап можно и пропустить
  1. Выбираем тип проекта
  2. Выбираем название
  3. Готово, можно приступать



Дальше немного усложним наше приложение


  1. Поменяем класс контроллера нашего первого View на MainViewController
    Вот так
    До:

    После(меняем название класса и файла):

    До:

    После(CustomClass справа сверху меняем на новый)):

  2. Добавим второй View и ViewController для него(назовем его SpecialViewController)
    Вот так
    Наводим мышку на нужный на тип контроллера(ViewController), и перетаскиваем на вкладку интерфейса(Drag-n-Drop), затем создаем класс для нашего нового контроллера SpecialViewController(базовый код стандртен и аналогичен коду главного контроллера на этом этапе) в новом файле под названием SpecialViewController.swift. Затем выбираем наш контроллер в визуальном редакторе и в его свойствах в вкладке CustomClass в поле Class выбираем из списка наш свежесозданный класс контроллера.


Итак, у нас теперь есть два окна, в одно из которых попасть у пользователя просто не получится.

Перейдем к программированию мышкой



1. Добавляем элементы в визуальный редактор

Это самая простая часть, делается как и везде.
Текстовому полю мы задали свойство Placeholder, оно позволяет выводить «приглашение для ввода», которое видно только пока не введено никакого текста. Но о свойствах не будем сильно распостраняться в рамках этой статьи, дабы не перегружать.
Для начала надо выбрать значок наверху, он нужен нам чтобы одновременно видеть контроллер в визуальном редакторе и код класса этого же контроллера. Затем просто «перетаскиваем» нужный нам элемент контроллера правой кнопкой мыши в визуальной половине на его код. Вам предложат произвольное название переменной, по которой теперь доступен элемент для всех функций контроллера.
Для этого нужны небольшие приготовления. Сначала кликаете пкм по нужному элементу, получаете вот такое окно:

Список событий здесь описывать не буду, они, имхо, самоочевидны. Выбираете нужное вам и левой кнопкой мыши перетаскиваете его в код.
Здесь мы по нажатию кнопки меняем текст Label на введенный пользователем. С демонстрацией работы на симуляторе под iPhone 6
Как наиболее внимательные читатели могли уже заметить, наш редактор ругается на невозможность попасть в SpecialView. И он прав! Именно для решения этой проблемы через визуальный редактор существует такое понятие как Segue. Благодаря им мы можем наглядно показать, откуда куда может попасть пользователь.

Переходы между окнами



1. Простейший вариант

Самый простой вариант — безусловный переход. Добавим для этого в наш проект кнопку «Перейти», нажмем над ней ПКМ и протащим появившуюся линию до того View, на который мы хотим получить переход(SpecialView в нашем случае). Получим запрос о типе Segue, выбираем там show — с остальным можете сами поэкспериментировать. Аналогично добавим в SpecialView кнопку назад, и прицепим к ней переход в MainView.
Как видите, простейшие переходы можно создавать не написав ни единой строчки кода. Но, естественно, далеко не всегда хватает безусловных переходов.

2. Добавим условный переход

Самый простой способ для этого — вызывать наш переход через код. Но ведь в коде его и нету. Да и по нажатию кнопки все равно срабатывать будет, а этого не хотелось бы. Выход довольно прост: удаляем старую версию перехода, а новую ведем не от нашей кнопки, а от желтого кружочка самого ViewController,  назовем наш переход MainToSpecial
Итак, пусть мы хотим пускать пользователя в SpecialView только если поле для ввода и Label содержат одинаковый текст.
Для этого нам надо создать для кнопки событие нажатия в контроллере, в нем проверять это условие. Если оно выполняется, выполним переход с помощью вот такого кода:
self.performSegueWithIdentifier("MainToSpecial", sender: self)//вместо MainToSpecial название любого из созданных вами переходов

Добавляется этот код вот так
Проверяем…
Все работает
Как видите, пускает на SpecialView только при одинаковых значениях в полях, а вот обратно — в любом случае, что нам и нужно.
На этом можно и закончить, но все-таки покажу напоследок асинхронную проверку условий перехода, т.к. имхо она не менее важна.

3. Асинхронный переход с проверкой условия на сервере

В общем-то отличий от синхронного варианта не слишком много:
  1. Проверка условия не происходит мгновенно и не может находиться в обработчике нажатия кнопки напрямую
  2. Надо как-то показывать пользователю, что он ждет
  3. Придется использовать коллбэки

Во-первых, вся логика приложения не имеющая свзяи с интерфейсом, должна находиться в отдельных классах, поэтому создадим класс Server в файле Server.swift с единственной функцией(код, конечно, не очень, но не хочу усложнять пример):
Скрытый текст
import UIKit

let server=Server()
class Server {
    private let apiURL="https://your-site?"//юрл сайта, который отвечает на ваши запросы JSON'ом
    func tryCheck(data:String,callback:(NSDictionary)->Void)//коллбэк - здесь должен быть обработчик интерфейса
    {
        let request=(self.apiURL + data)
        let encoded = request.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
        var url: NSURL = NSURL(fileURLWithPath: encoded!)!
        var session = NSURLSession.sharedSession()
       //следующая команда выполняется асинхронно - отправляет запрос и не ждет ответа 
       // для обработки этого ответа надо дать ей коллбэк, в который мы поместим наш коллбэк 
        var task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in 
            println("Task completed")
            if((error) != nil) {
                println(error.localizedDescription)
            }
            var err: NSError?
            var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
            if (err? != nil) {
                println(error.localizedDescription)
            }
            dispatch_async(dispatch_get_main_queue(), {
                callback(jsonResult)//здесь мы передаем даные о происходящем интерфейсу
            })
        })
        task.resume()
    }
}


Сервер не указан специально, т.к. хабраэффект. Так что эту часть приложения вы сможете затестить только со своим сервером, либо используя для тестирования чужой публичный webAPI.
В этом коде мы делаем запрос, и в случае получения ответа отправляем его в переданный нам из UI коллбэк.
Код MainViewController поменяется на такой:
Скрытый текст
    @IBAction func MtoS(sender: AnyObject) {
        server.tryCheck( WhereLbl.text! + FromText.text!, callback: onResponse)
    }
    
    func onResponse(json:NSDictionary) {
        if json["code"] as String == "ok" { //допустим, что если сервер считает переход корректным, он пошлет нам {"code":"ok"}
            self.performSegueWithIdentifier("MainToSpecial", sender: self)//все ок, делаем переход
        } else {
            self.WhereLbl.text="Forbidden!"//иначе сообщаем о неудаче
        }
    }


И остается один неприятный, но важный момент — показать пользователю задержку. Для это есть специальный компонент UIActivityIndicatorView, причем мы сразу выставляем ему свойство HidesWhenStopped чтобы он был виден только при анимации, при начале асинхронного запроса мы его анимацию включаем, а при получении ответа в нашем коллбеке — выключаем.
Много чего еще можно написать о программировании на Swift в XCode, но пока остановимся на этом.
Надеюсь, что статья принесет пользу новичкам, а может и не только им(хе-хе).