суббота, 16 апреля 2016 г.

Ваше первое iOS приложение | Applifto.ru


Ваше первое iOS приложение

Эта статья расскажет вам о трёх правилах в разработке iOS приложений:

Инструменты

Как использовать Xcode для создания проектов и управления ими.

Технологии

Как создать приложение, отвечающее ожиданиям пользователей.

Методы

Как использовать в своих интересах базовые шаблоны разработки, которые лежат в основе всех iOS приложений.

После того как вы ознакомитесь со всеми этапами этого руководства, у вас будет приложение похожее на это:

Как показано выше, в созданном вами приложении есть всего три основных элемента пользовательского интерфейса:

  1. Текстовое поле, куда пользователь вводит данные
  2. Ярлык, в котором приложение отображает данные
  3. Кнопка, при нажатии на которую приложение отображает данные в ярлыке

Когда вы запускаете готовое приложение, при нажатии на текстовое поле появляется встроенная системная клавиатура. С помощью клавиатуры введите своё имя и нажмите кнопку Done. После нажмите на кнопку Hello, чтобы увидеть строку «Hello Your Name!» в ярлыке между текстовым полем и кнопкой.

Материал по теме: Xcode 6: рендеринг в реальном времени, визуальная отладка представлений и Swift

Польза этого руководства в том, что оно знакомит вас с основами программирования в целом и с объектно-ориентированным программированием и языком Objective C в частности. Не переживайте о том, сможете ли вы понять код в этом руководстве, если ранее вы никогда не использовали Objective C. К моменту окончания работы с этим руководством вы будете понимать код куда лучше.

Обратите внимание: вы можете использовать это руководство для разработки приложений для iOS даже, если в будущем вы намерены заниматься разработкой исключительно для iPad. Несмотря на то, что это руководство показывает пользовательский интерфейс iPhone, инструменты и методы для работы не отличаются от тех, которые используются для разработки iPad приложений.

Приступая к работе

Для создания iOS приложения с помощью этого руководства вам потребуется Xcode версии 4.3 или позднее. Xcode — это встроенная среда разработки Apple как для iOS, так и для Mac OS. При установке Xcode на Mac вы также устанавливаете пакет программ разработчика iOS, в который входят интерфейсы программирования для платформы iOS.

Создание и тестирование нового проекта

Для того, чтобы начать разработку вашего приложения, создайте новый проект в Xcode.

Для создания нового проекта:

1. Откройте Xcode (по умолчанию он находится в каталоге /Applications).

Если вы никогда ранее не создавали и не открывали проекты в Xcode, вам полезно будет ознакомиться с Окном приветствия Xcode:

2. В окне приветствия Xcode кликните Create a new Xcode project (или выберите File > New > Project).

Xcode откроет новое окно и покажет меню, в котором вы сможете выбрать шаблон. Xcode включает в себя несколько встроенных шаблонов приложений, которые вы можете использовать при разработке iOS приложений стандартного вида. Например, шаблон Tabbed позволяет создать приложение, схожее внешним видом с iTunes, а шаблон Master-Detail создаёт приложения похожие на Mail.

3. В разделе iOS с левой стороны от диалогового окна выберите Application.

4. В основной части диалогового окна выберите Single View Application и нажмите Next.

Появится новое окно подсказки, которое предложит дать имя вашему проекту и выбрать дополнительные опции для него.

5. Заполните поля Product Name, Company Identifier и Class Prefix. Вы можете использовать следующие значения:

Product Name: HelloWorld

Company Identifier: Идентификатор вашей компании, если у вас такой имеется. В случае, если у вас ещё нет идентификатора, вы можете использовать значение edu.self.

Class Prefix: HelloWorld

Обратите внимание: введённое имя Xcode будет использовать для названия вашего проекта и будущего приложения. Xcode использует имя префикса класса для того, чтобы обозначить классы, созданные для вас. Например, Xcode автоматически создаёт делегата приложения класса и называет егоHelloWorldAppDelegate. Если вы назовёте префикс класса иначе, то делегат класса приложения будет называться ИмяПрефиксаКлассаДелегатПриложения (YourClassPrefixNameAppDelegate). О делегатах приложения вы узнаете больше в главе «Как работает приложение». Для простоты работы с данным руководством предполагается, что вы назвали свой продукт HelloWorld иHelloWorld используется в значении префикса класса.

  • Проверьте, чтобы в всплывающем меню Device Family был выбран пункт iPhone.
  • Проверьте, чтобы опции Use Storyboards и Use Automatic Reference Counting были выбраны, а опция Include Unit Tests была отключена.
  • Нажмите Next. Новое всплывающее окно подсказки уточнит, в какой каталог следует сохранить ваш проект
  • Определите место записи проекта (оставьте опцию Source Control неактивной) и кликните на Create.

Xcode откроет новый проект в окне, называемом окном рабочего пространства, которое будет выглядеть следующим образом:

Потратьте несколько минут, чтобы ознакомиться с окном рабочего пространства, которое откроет Xcode. С кнопками, инструментами и рабочими областями, указанными ниже, вы будете сталкиваться постоянно по ходу работы с данным руководством.

Если область утилит в рабочем окне уже открыта (как показано на рисунке выше), можете закрыть её, так как в данный момент она вам не нужна. Кнопка View, находящаяся справа, управляет областью утилит. Когда область утилит видима, кнопка выглядит следующим образом:

При необходимости нажмите на кнопку View, чтобы закрыть область утилит.

Материал по теме: Подробно о Xamarin

Даже если вы ещё не записали ни строчки кода, вы можете создать приложение и запустить его во встроенном в Xcode приложении Симулятор. Как следует из названия, Симулятор даёт возможность оценить работу и внешний вид вашего приложения как если бы оно было запущено на iOS устройстве.

Для запуска приложения в Симуляторе:

  1. Проверьте, чтобы у всплывающего меню Scheme на панели инструментов Xcode выбран параметр HelloWorld > iPhone 5.0 Simulator.

    Если всплывающее меню не отображает меню выбора, то откройте его вручную и выберите iPhone 5.0 Симулятор.

  2. Нажмите кнопку Run на панели инструментов Xcode (или выберите Product > Run).

    Xcode выводит на экран сообщения о процессе сборки в окне просмотра действий, которое находится в середине панели инструментов.

После того, как Xcode закончит сборку проекта, Симулятор запустится автоматически (возможно, придётся подождать несколько секунд, прежде чем Симулятор отобразится поверх рабочего окна). Так как вы выбрали iPhone устройство, а не iPad, то Симулятор отобразит окно, похожее на iPhone. На смоделированном экране iPhone Симулятор откроет приложение, которое будет выглядеть следующим образом:

Пока что приложение выглядит скучным — всего-лишь пустой белый экран. Чтобы понять, откуда появляется белый экран, вам нужно узнать об объектах кода и как они взаимодействуют в работе приложения. Сейчас вам необходимо закрыть Симулятор, для этого выберите iOS Simulator > Quit iOS Simulator. Будьте внимательны и не закройте случайно сам Xcode.

Материал по теме: Пишем backend для мобильного приложения за несколько минут

Когда вы запускаете приложение, Xcode может открыть область исправления ошибок в нижней части рабочего окна. В этом руководстве вы не будете использовать эту область, так что можете её закрыть, чтобы у вас было больше место для рабочего окна.

Чтобы закрыть область исправления ошибок:

Нажмите кнопку Debug View на панели инструментов. Кнопка Debug View находится посередине и выглядит следующим образом:

Как работает приложение

Поскольку для своего проекта вы использовали шаблон Xcode, то большая часть элементов среды приложения устанавливается автоматически при запуске приложения. Например, Xcode создаёт объект приложения, который, среди прочего, устанавливает цикл выполнения (цикл выполнения регистрирует вводимый код и делает возможной работу вводимых событий в приложении). Большая часть этой работы выполняется функцией UIApplicationMain, которая представлена платформой UIKit и вызывается автоматически в исходном файле вашего проекта main.m.

Примечание: платформа UIKit предоставляет все возможные классы, необходимые приложению для создания и управления пользовательским интерфейсом. Платформа UIKit — всего-лишь одна из многих объектно-ориентированных платформ, созданная CocoaTouch, которая является средой приложения для всех iOS приложений.

Чтобы открыть исходный файл main.m необходимо:

  1. Убедитесь, что навигатор проекта открыт в области навигатора.

    Навигатор проекта отображает все файлы вашего проекта. Если навигатор проекта закрыт, то нажмите следующую кнопку на панели:

  2. Откройте папку Supporting Files в навигаторе проекта, нажав на треугольник:
  3. Выберите main.m.

    Xcode открывает исходный файл в главном редакторе окна, который выглядит следующим образом:

Основная функция main.m вызывает функцию UIApplicationMain в autorelease-пуле:

@autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([HelloWorldAppDelegate class])); }

Оператор @autoreleasepool поддерживает систему автоматического подсчёта ссылок (ARC system). Система ARC автоматически управляет временем жизни объекта, гарантируя существование объектов на период их использования, но не дольше.

Обращение к UIApplicationMain создаёт экземпляр класса UIApplication и экземпляр делегата приложения (в данном руководстве делегатом приложения является HelloWorldAppDelegate, предоставленный шаблоном Single View). Основная задача делегата приложения — определять окно, в котором отображается контент приложения. Кроме того, делегат приложения может осуществлять некоторые задачи конфигурации до момента отображения приложения. (Делегирование — шаблон проектирования, в котором один объект действует от имени другого объекта или сообразуясь с ним.)

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

Обращение к UIApplicationMain также сканирует файл приложения Info.plist. Файл Info.plist — это список свойств (структурированный список пар ключ-значение), который содержит такую информацию о приложении как название и иконка.

Чтобы открыть этот список свойств необходимо:

  • Выбрать HelloWorld-Info.plist в папке Supporting Files в навигаторе проекта.

    Xcode откроет файл Info.plist в редакторе рабочего окна, которое будет выглядеть следующим образом:

    В этом руководстве вам не потребуется изучать остальные файлы в папке Supporting Files, так что вы можете закрыть папку в навигаторе проекта и более не отвлекаться на неё. Кликните ещё раз на треугольник рядом со значком для того, чтобы закрыть папку Supporting Files.

Поскольку в нашем проекте мы выбрали использование раскадровки, то файл Info.plist будет содержать также название файла раскадровки, загружаемого объектом приложения. Раскадровка содержит в себе архив объектов, переходов и связей, определяющих пользовательский интерфейс приложения.

В приложении HelloWorld файл раскадровки назван MainStoryboard.storyboard (обратите внимание, что файлInfo.plist показывает только первую часть имени). При запуске приложения загружаетсяMainStoryboard.storyboard и initial view controller реализуется именно из него. View controller — объект, управляющий областью контента; initial view controller — первый view controller, загружаемый при запуске приложения.

Приложение HelloWorld содержит всего один view controller, в данном случае — HelloWorldViewController. Сейчас контроллер HelloWorldViewController управляет областью контента, представленного единственным элементом view.View (представление) — это объект, рисующий контент в прямоугольной области экрана и управляющий событиями, вызванными касаниями экрана пользователем. Представление также может содержать другие представления, называемыесубпредставлениями. При добавлении субпредставления к представлению контейнер называется родительскимпредставлением, а его субпредставление называется дочерним представлением. Сочетание родительского представления, его дочерних представлений (а также их дочерних представлений, если таковые имеются) образует иерархию представлений. View controller управляет одной иерархией представлений.

Материал по теме: RevealApp — Firebug для iOS приложений

Обратите внимание: В приложении HelloWorld представления и контроллер представления представляют две из трех ролей для объектов приложения, определяемые шаблоном разработки Model-View-Controller (MVC). Третья роль — модель. В шаблоне MVC модели представляют собой данные (как элемент to-do списка в приложении-календаре или же фигура в приложении для рисования), представления знают, каким образом отображать данные, представленные моделями, а контроллеры связывают между собой модели и представления. В приложении HelloWorld модель является строкой, содержащей имя, вводимое пользователем. В данный момент это всё, что вам необходимо знать о MVC, однако уже пора начать задумываться о том, каким образом разные объекты вашего приложения играют ту или иную роль.

Позже вы будете создавать иерархию представлений, добавляя три субпредставления к представлению, управляемому посредством HelloWorldViewController. Эти три субпредставления будут представлять собой текстовое поле, ярлык и кнопку.

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

Чтобы открыть окно раскадровки необходимо:

  • Выбрать MainStoryboard.storyboard в навигаторе проекта.

    Xcode откроет раскадровку в окне редактора. Область позади объектов раскадровки, та, которая выглядит как линованная бумага, называется canvas.

При открытии раскадровки окно рабочего пространства будет выглядеть следующим образом:

Раскадровка содержит сцены и переходы. Сцена представляет собой view controller, а переход является переходом между двумя сценами.

Поскольку шаблон Single View предоставляет только один view controller, в раскадровке вашего приложения есть одна сцена, но ни одного перехода. Стрелка, которая указывает на левую часть сцены на canvas, является индикатором начальной сцены, она идентифицирует сцену, загружаемую при запуске приложения в первую очередь (как правило, начальная сцена совпадает с inital view controller).

Сцена, которую вы видите на canvas, называется Hello World View Controller по причине того, что она управляется объектом HelloWorldViewController. Сцена Hello World View Controller состоит из нескольких элементов, которые отображаются в Xcode outline view (панель между canvas и навигатором проекта). Сейчас view controller содержит следующие элементы:

  • Объект-заполнитель first responder (на картинке обозначен кубиком оранжевого цвета).

    First responder — динамический заполнитель, представляющий объект, который при работе приложения первым будет получать различные события. К ним относятся события со смещением фокуса (к примеру, при тапе на текстовое поле для вызова клавиатуры), события движения (встряхивание устройства) и события сообщений (например, сообщение, отправляемое при нажатии кнопки). В этом руководстве мы не будем использовать first responder.

  • Объект HelloWorldViewController, отмеченный светлым квадратом в жёлтом круге.

    Когда storyboard загружает сцену, он создаёт экземпляр класса view controller, который будет управлять этой сценой.

  • Представление, находящееся под view controller (возможно, для того чтобы увидеть это представление, вам потребуется открыть стрелку рядом с Hello World View Controller).

    Белый фон этого представления отображает то, что вы увидите при запуске приложения в Simulator.

Обратите внимание: объект окна приложения не представлен в storyboard.

Область на canvas под сценой называется scene dock. В данный момент scene dock отображает название контроллера, т.е. Hello World View Controller. В других случаях scene dock может содержать иконки, представляющие first responder и объект view controller.

Итог

В этой главе вы использовали Xcode для создания нового проекта на основе шаблона Single View, а также собрали и запустили базовое приложение, сделанное на основе этого шаблона. После вы ознакомились с базовыми элементами проекта, такими как файл с исходным кодом main.m, файл Info.plist и файл storyboard, а также узнали как работает приложение. Ещё вы узнали о шаблоне Model-View-Controller, который определяет роли объектов приложения.

В следующей части вы узнаете ещё больше о view controller и элементах view.

Изучение контроллера и его представления

Как вы узнали чуть раньше, view controller отвечает за управление сценой, которая представляет одну область контента. Контент, который вы видите в этой области, определяется с помощью представления этого элемента. В этой части вы подробно ознакомитесь со сценой, управляемой контроллером HelloWorldViewController, и узнаете, как задать цвет фона его представления.

Использование Inspector для исследования View Controller

При запуске приложения загружается основной файл storyboard и создаётся экземпляр initial view controller. Initial view controller управляет первой сценой, которую видит пользователь при запуске приложения. В используемом шаблоне Single View представлен только один view controller, по этой причине автоматически устанавливается initial view controller. Вы можете подтвердить статус view controller и узнать подробнее о нём с помощью Xcode inspector.

Чтобы открыть inspector необходимо:

  1. При необходимости кликните на MainStoryboard.storyboard в навигаторе проекта, чтобы отобразить сцену в поле canvas.
  2. На панели outline view выберите Hello World View Controller (он находится в списке под First Responder).

    Ваше рабочее пространство будет выглядеть следующим образом:

    Обратите внимание, что scene dock и сцена выделены синим цветом, а объект view controller выделен в поле scene dock.

  3. При необходимости нажмите на кнопку View справа, чтобы отобразить область утилит в правой части окна, или же нажмите View > Utilities > Show Utilities.
  4. Чтобы открыть свойства Inspector, нажмите кнопку Attributes inspector в области утилит.

    Кнопка Attributes inspector четвёртая слева:

    При открытом окне Attributes inspector ваше рабочее пространство будет выглядеть следующим образом (возможно, вам придётся изменить размер окна, чтобы увидеть все элементы):

    В разделе View Controller инспектора атрибутов вы увидите выбранную функцию Initial Scene:

    Обратите внимание, что если вы отключите эту опцию, индикатор initial scene исчезнет из области canvas. Для работы с этим руководством проверьте ещё раз, что выбрана опция Initial Scene.

Изменение цвета фона View

Ранее в этом руководстве вы узнали, что фоновым цветом view, который вы видите при запуске приложения в симуляторе, является белый. Чтобы убедиться в корректной работе приложения, вы можете изменить фоновый цвет view на какой-либо другой и удостовериться в этом, запустив Simulator.

Прежде чем вы измените цвет view, убедитесь в том, что storyboard все ещё открыт в поле canvas. (При необходимости кликните на MainStoryboard.storyboard в навигаторе проекта, чтобы отобразить storyboard в поле canvas.)

Для того, чтобы изменить фоновый цвет view controller необходимо:

  1. На панели outline view кликнуть на стрелку рядом с Hello World View Controller (в случае, если он ещё не открыт) и выбратьView.

    Xcode подсвечивает область view в поле canvas.

  2. Нажмите кнопку Attributes на панели inspector, чтобы открыть Attributes inspector, если он ещё не открыт.
  3. Во вкладке Attributes inspector кликните на белый прямоугольник в меню Background и откройте вкладку Colors.

    Прямоугольник показывает текущий фоновый цвет элемента. Меню Background выглядит так:

    Обратите внимание: если вместо клика по белому прямоугольнику вы кликните на Default и откроете меню, то выберите вариант Other.

  4. В окне Colors выберите цвет, отличный от белого.

    Ваше рабочее пространство и вкладка Colors должны выглядеть следующим образом:

    Обратите внимание: поскольку Xcode подсвечивает элемент view когда тот выбран, цвет в поле canvas может отличаться от того, который вы выбрали во вкладке Colors.

  5. Закройте окно Colors.

Кликните на кнопку Run (или выберите Product > Run) для того, чтобы протестировать своё приложение в Simulator. Убедитесь, что меню Scheme на панели инструментов Xcode все ещё показывает HelloWorld > iPhone 5.0 Simulator. Вы увидите примерно следующее:

Подсказка. Сохранять приложение перед запуском необязательно, т.к. Xcode автоматически сохраняет файлы, в которых были совершены изменения.

Прежде чем вы продолжите работу с этим руководством, верните фоновый цвет view и сделайте его снова белым.

Чтобы вернуть цвет фона view необходимо:

  1. Нажимая на стрелки в окне Attributes inspector открыть меню Background.

    Обратите внимание, что прямоугольник в меню Background изменил свой цвет на выбранный вами во вкладке Colors. При повторном клике на цветной прямоугольник (а не на стрелки) снова откроется вкладка Colors. Поскольку вы хотите вновь использовать изначальный цвет фона, то проще открыть меню Background, чем заново искать нужный цвет во вкладке Colors.

  2. Во всплывающем меню Background выберите белый квадрат среди недавно использованных цветов — Recently Used Colors.
  3. Кликните на кнопку Run для компиляции и запуска приложения (внесённые изменения будут сохранены).

После того, как вы убедитесь, что изменили цвет фона обратно на белый, можете закрыть симулятор

Итог

В этой части вы изучили сцену и изменили цвет фона элемента view, а после вернули его к изначальному.

В следующей части мы добавим к элементу view текстовое поле, ярлык и кнопку, позволяющую пользователю взаимодействовать с вашим приложением.

Настройка View

Xcode предоставляет библиотеку объектов, которые вы можете добавлять в файл storyboard. Некоторые из этих элементов пользовательского интерфейса относятся к view, например, кнопки и текстовые поля. Другие объекты относятся к более высокому уровню, к примеру, контроллеры view controllers и распознаватели жестов.

Сцена Hello World View Controller уже содержит в себе элемент view, теперь нам необходимо добавить кнопку, ярлык и текстовое поле. Таким образом вы задаёте связи между этими элементами и классом view controller, и элементы будут выполнять желаемые вами функции.

Добавление элементов пользовательского интерфейса

Вы добавляете элементы пользовательского интерфейса (далее UI-элементы), перетаскивая их из библиотеки объектов к элементу view в области canvas. После того как UI-элементы добавлены в представление, вы можете менять их положение и размер.

Чтобы добавить UI-элементы во view и расположить их соответствующим образом вам необходимо:

  1. При необходимости кликните на MainStoryboard.storyboard в навигаторе проекта, чтобы отобразить сцену Hello World View Controller в поле canvas.
  2. При необходимости откройте библиотеку объектов.

    Библиотека объектов появится в нижней части области утилит. Если вы все ещё не видите библиотеку объектов, кликните на третью кнопку слева на панели выбора библиотеки:

  3. В библиотеке объектов выберите Controls из меню объектов. Xcode отображает список controls ниже всплывающего меню. В списке отображены название каждого элемента управления, его внешний вид, а также краткое описание его функций.
  4. Поочерёдно перетащите из списка text field, round rect button, и label, и разместите их на представлении.

  5. Перетащите текстовое поле в верхний левый угол представления. При перемещении текстового поля (или любого другого UI-элемента) ориентируйтесь по синим линиям, т.н. alignment guides или же направляющим выравнивания. Они помогают расположить элемент ровно по центру или же по краям представления. Тяните текстовое поле до тех пор, пока оно не встанет также, как на рисунке ниже:

  6. Приготовьтесь изменить размер текстового поля в представлении. Изменять размер UI-элементов можно с помощью маленьких белых квадратных скобок по краям элемента, удерживая их зажатыми. Чтобы увидеть эти скобки выделите объект в области canvas или outline view. В данном случае объект уже выбран, т.к. вы только что изменяли его размер путём растягивания. Если ваше текстовое поле выглядит также, значит вы уже можете изменять его размер. Если же оно выглядит иначе, необходимо его выделить.

  7. Тяните текстовое поле вправо до тех пор, пока на view не появятся направляющие выравнивания. Можно перестать менять размер текстового поля, когда оно будет выглядеть следующим образом:

  8. Пока текстовое поле все ещё выделено, откройте Attributes inspector.
  9. Введите фразу Ваше имя в поле Placeholder в верхней части инспектора атрибутов текстового поля.

    Как видно из названия, поле Placeholder выводит текст светло-серого цвета, подсказывающий пользователю, какого рода данные он может ввести в это текстовое поле. При запущенном приложении текст placeholder'а исчезает после того, как пользователь нажмёт на текстовое поле.

  10. Не закрывайте инспектор атрибутов текстового поля, кликните на среднюю кнопку Alignment, чтобы отцентрировать текст в текстовом поле.

    После того, как вы введёте текст и измените настройки выравнивания, окно Text Field Attributes inspector будет выглядеть следующим образом:

  11. В области view перетащите ярлык таким образом, чтобы он оказался под текстовым полем и был выровнен с ним по левому краю.
  12. Растяните ярлык по ширине до соответствия с шириной текстового поля.

    У ярлыка больше возможностей изменения размера в отличие от текстового поля, так как кроме ширины у него ещё есть высота (в то время как у текстового поля вы можете настраивать только ширину). Мы не хотим менять высоту ярлыка, а потому будьте аккуратнее и не зацепите угловые скобки ярлыка. Тяните за среднюю скобку с правой стороны ярлыка.

  13. Во инспекторе атрибутов ярлыка нажмите среднюю кнопку Alignment, чтобы текст, отображаемый в ярлыке находился по центру.
  14. Перетащите кнопку к нижней части view и установите её посередине.
  15. Кликните дважды на кнопке в области canvas и введите текст Hello.

    Когда вы дважды кликните по кнопке в области view (ещё до того как введёте текст), вы увидите нечто подобное:

    После того как вы добавите UI-элементы: текстовое поле, ярлык и кнопку, и примените рекомендуемые изменения во внешнем виде, ваше приложение будет вяглядеть следующим образом:

Есть ещё определенные изменения, которые вы можете применить к текстовому полю, чтобы оно работало в соответствии с ожиданиями пользователя. Для начала, так как предполагается, что пользователь будет вводить своё имя, используйте функцию заглавных букв каждого нового слова, предлагаемую iOS. Во-вторых, вы можете убедиться, что клаватура связана с текстовым полем и настроена для ввода имён, а не цифр, к примеру, и что на клавиатуре высвечивается кнопка Done.

Материал по теме: Pro Core Data for iOS. Глава № 1. Теоретическая часть

Принцип изменений прост: поскольку во время разработки приложения вы знаете какой тип информации будет содержать то или иное текстовое поле, вы можете настроить их внешний вид и поведение в соответствии с задачами пользователя. Все эти изменения вы осуществляете в Attributes inspector.

Для настройки текстового поля необходимо:

  1. В области view выбрать текстовое поле.
  2. В окне инспекторе атрибутов текстового поля сделать следующие изменения:
  • в меню Capitalization выбрать Words.
  • Убедиться, что меню Keyboard установлено на Default.
  • Во всплывающем меню Return Key выбрать Done.

    После внесения этих изменений инспектор атрибутов текстового поля будет выглядеть следующим образом:

    Запустите своё приложение в Simulator и проверьте, что те UI-элементы, которые вы добавили, выглядят именно так, как вы хотите. Если вы нажмёте на кнопку «Hello», она должна быть подсвечена. Если вы кликните на текстовое поле, должна появиться клавиатура. В данный момент кнопка не выполняет никаких функций, ярлык просто отображает надпись «Label» и нет возможности свернуть клавиатуру. Для добавления необходимого функционала вам потребуется создать соответствующие связи между UI-элементами и view controller. Эти связи описаны далее.

Обратите внимание: поскольку вы запускаете приложение в Simulator, то для активации функций управления вы кликаете на них, а не делаете тап.

Создание действия для кнопки

Когда пользователь активирует UI-элемент, этот элемент отправляет сообщение о событии объекту, который знает, как выполнить соответствующее действие (к примеру, «добавить контакт в список контактов пользователя»). Такое взаимодействие является частью механизма target-action, который является ещё одним шаблоном проектирования Cocoa Touch.

В данном руководстве, при тапе на кнопку «Hello» вы хотите отправить сообщение «изменить приветствие» (action) во view controller (target). Это сообщение меняет строку (т.е. модель), управляемую view controller'ом. View controller обновит текст на ярлыке, чтобы отразить изменения в модели.

При использовании Xcode вы можете добавлять действия к UI-элементам и задавать им соответствующие методы с помощью перетаскивания элемента управления на canvas в соответствующий исходный файл (обычно, в исходный файл view controller'а). Storyboard записывает созданные вами связи. После этого, когда приложение загрузит storyboard, созданные связи будут восстановлены.

Чтобы добавить действие для кнопки необходимо:

1. При необходимости выберите MainStoryboard.storyboard в навигаторе проекта, чтобы отобразить сцену на canvas.

2. На панели инструментов XCode кликните кнопку Utilities, чтобы скрыть область утилит и кликните кнопку assistant editor чтобы открыть панель Assistant editor.

Кнопка assistant находится посередине и выглядит следующим образом:

3. Убедитесь, что Assistant отображает заголовок файла view controller'а (в данном случае, HelloWorldViewController.h).

4. На области canvas перетащите элемент управления с кнопки «Hello» в область объявления методов в HelloWorldViewController.h (в данном случае, между оператором @interface и оператором @end).

Для перетаскивания нажмите и держите клавишу Control

После того, как вы закончите перестаскивание, у вас должно получиться следующее:

После этого Xcode должен отобразить вспомогательный экран, на котором вы сможете настроить связи действий:

Обратите внимание: если вы отпустите клавишу Сontrol в другом месте, а не в области объявления метода HelloWorldViewController.h, то у вас может появиться другой вспомогательный экран, или же вообще ничего не произойдёт. Если это произошло, кликните на область view в canvas и при необходимости закройте вспомогательный экран и попробуйте перетащить элемент управления ещё раз.

5. На вспомогательном экране настройте связи действия для кнопки:

  • в меню Connection выберите Action.
  • В поле Name введите changeGreeting:(не забудьте про двоеточие!).

    В дальнейшем вы будете использовать метод changeGreeting: для того, чтобы он брал имя, введённое пользователем, и отображал его в ярлыке.

  • Убедитесь, что в поле Type выбрано значение id.

    Тип данных id может быть представлен любым объектом Cocoa. Вы используете id по той причине, что вам совершенно безразлично какой тип объектов будет отправлять сообщение.

  • Убедитесь, что во всплывающем меню Event выбрано значение Touch Up Inside.

    Вы задаёте событие Touch Up Inside поскольку хотите, чтобы сообщение отправлялось при помещении пользователем пальца на кнопку.

  • Убедитесь, что во всплывающем меню Arguments выбрано значение Sender.

    После того, как вы настроите связи действий, ваш вспомогательный экран должен выглядеть следующим образом:

6. На вспомогательном экране нажмите Connect. Xcode добавляет заготовку нового метода changeGreeting: и указывает на наличие связи отображением заполненного кружка с левой стороны от метода:

Перетащив Control-кликом кнопку «Hello» в файл HelloWorldViewController.h и настроив последующие действия, вы выполнили две вещи:

  • Добавили соответствующий код в класс view controller. В данном случае вы добавили следующее объявление метода действия в файл HelloWorldViewController.h:

    - (IBAction)changeGreeting:(id)sender;

    что вынудило Xcode добавить следующую заготовку к HelloWorldViewController.m:

    - (IBAction)changeGreeting:(id)sender { }

    Обратите внимание: IBAction — специальное ключевое слово, которое используется, чтобы сообщить Xcode, чтобы он использовал метод в качестве action в target-action связях. IBAction имеет значение void. Параметр sender в action-методе ссылается на объект, отправляющий action-сообщение (в данном руководстве, sender является кнопкой).

  • Вы создали связь между кнопкой и view controller'ом.

Далее вы создадите связи между view controller'ом и двумя оставшимися UI-элементами: ярлыком и текстовым полем.

Создание аутлетов для текстового поля и ярлыка.

Аутлет описывает связь между двумя объектами. Когда вы хотите связать два объекта, к примеру, view controller и текстовое поле, вы создаёте автономный объект, т.е. аутлет. При запуске приложения созданный вами в Xcode аутлет сохраняется, что позволяет объектам взаимодействовать между собой.

В данном руководстве вам необходимо, чтобы view controller получал текст, введённый пользователем в текстовое поле, а затем отображал его в ярлыке. Чтобы view controller взаимодействовал с этими объектами, вы создаёте аутлет связи между ними.

Добавление аутлета для текстового поля и ярлыка очень похоже на добавление действия к кнопке, которое вы делали ранее. Прежде, чем вы начнёте, проверьте, открыт ли у вас основной файл storyboard в области canvas. HelloWorldViewController.h должен быть открыт в Assistant editor.

Чтобы добавить аутлет к текстовому полю необходимо:

1. Сделайте Control-кликом из текстового поля в области view в область объявления метода в файл заголовка.

После перетаскивания у вас должно получиться приблизительно следующее:

Внутри области объявления метода совершенно не имеет значение, когда вы отпустите Control. В данном руководстве объявление аутлетов для текстового поля и ярлыка приведены над объявлением метода для кнопки «Hello»

2. На появившемся вспомогательном экране настройте связи текстового поля:

  • Проверьте, чтобы в поле Connection был указан Outlet.
  • В поле Name введитеtextField.

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

  • Проверьте, чтобы поле Type имело значение UITextField.

    Задавая тип поля UITextField, вы гарантируете, что Xcode свяжет аутлет только с текстовым полем.

  • Проверьте, чтобы поле Storage имело значение Weak, это значение стоит по умолчанию.

После внесения изменений вспомогательный экран будет выглядеть следующим образом:

3. На вспомогательном экране нажмите Connect.

Добавив аутлет для текстового поля вы выполнили две задачи:

  • Добавили соотвествующий код в класс view controller'а. Т.е. вы добавили следующее объявление к HelloWorldViewController.h: @property (weak, nonatomic) IBOutlet UITextField *textField;
    Обратите внимание: IBOutlet — специальное ключевое слово, используемое только для того, чтобы сказать Xcode использовать объект в качестве аутлета. Оно не имеет никакого значения и не играет никакой роли во время компиляции.

    Также вы добавили следующее объявление к методу viewDidUnload в HelloWorldViewController.m:

    [self setTextField:nil];

    Метод viewDidUnload предоставлен выбранным вами шаблоном Xcode и реализован фреймворком UIKit. View controller вызывает viewDidUnload для выгрузки содержащихся в нём view. Поэтому этот метод лучше всего подходит для установки аутлетов представления в nil

  • Вы создали связь между текстовым полем и view controller'ом.

    Создание такой связи осуществляет передачу вводимого пользователем текста во view controller. С объявлением метода changeGreeting: в Xcode появится индикатор наличия связей в виде заполненного кружка с левой стороны.

Теперь добавьте аутлет для ярлыка и настройте связь. Создание связи между view controller и ярлыком позволяет записать в ярлык строку текста, введённую пользователем. Порядок действий в этом случае такой же как и в добавлении аутлета для текстового поля, но с учетом определенных изменений в настройках аутлета. (Проверьте, чтобы HelloWorldViewController.h был открыт в Assistant editor.)

Чтобы добавить аутлет к ярлыку необходимо:

1. Сделать Control-клик из ярлыка в области view в область объявления метода в файле HelloWorldViewController.h, открытом в Assistant editor.

2. На появившемся вспомогательном экране настройте связи ярлыка:

  • Проверьте, чтобы в поле Connection был указан Outlet.
  • В поле Name введите label.
  • Убедитесь, что поле Type имеет значение UILabel.
  • Проверьте, чтобы поле Storage имело значение Weak.

3. На вспомогательном экране нажмите Connect.

К этому моменту вы создали три связи для view controller:

  • Связь действия для кнопки
  • Связь аутлета для текстового поля
  • Связь аутлета для ярлыка

Проверить все эти связи вы можете через Connections inspector.

Чтобы открыть Connections inspector для view controller необходимо:

  1. Нажать кнопку Standard, чтобы закрыть Assistant editor и переключиться на стандартный редактор.

    Кнопка Standard — первая слева в группе Editor и выглядит так:

  2. Нажмите кнопку Utilities в группе View, чтобы открыть область утилит.
  3. Выберите Hello World View Controller.
  4. Откройте Connections inspector в области утилит.

    Кнопка Connections inspector находится справа на панели выбора инспекторов и выглядит так:

В инспекторе связей будут показаны свзяи для выбранного объекта, в данном случае, для view controller'а. Вы увидите приблизительно следующее:

Обратите внимание на наличие ещё одной связи между view controller и его view, в дополнение к уже созданным вами связям. Xcode сам создаёт такую связь между view controller и view; в любом случае вам не придётся производить над ней какие-либо действия.

Создание связи для делегата текстового поля

В приложении нужно создать ещё одну связь: необходимо связать текстовое поле с объектом, который вы объявляете делегатом. В данном руководстве вы используете view controller для делегата текстового поля.

Необходимо задать делегат для текстового поля, т.к. текстовое поле отправляет сообщение своему делегату при тапе на кнопку Done. В дальнейшем вы будете использовать этот же метод для сообщения, которое будет убирать клавиатуру с экрана устройства.

Проверьте, чтобы файл storyboard был открыт в области canvas. Если его там нет, выберите MainStoryboard.storyboard в навигаторе проекта.

Для установки делегата текстового поля необходимо:

  1. В области view, сделать Control-клик из текстового поля в жёлтый кружок в поле scene dock (жёлтый кружок показывает наличие объекта view controller).

    После этого вы увидите приблизительно следующее:

  2. В разделе Outlets выберите delegate из появившегося списка.

Тестирование приложения

Нажмите кнопку Run, чтобы протестировать приложение.

Вы увидите, как подсвечивается кнопка «Hello» при клике на неё. Также вы увидите, что при клике на текстовое поле появляется клавиатура для ввода текста. Однако у нас все ещё нет возможности скрыть клавиатуру. Чтобы добавить такую возможность необходимо добавить соответствующий метод делегата. Это мы сделаем в следующей части. Сейчас вы можете закрыть Simulator.

Итог

После создания соответствующих связей между view controller в области canvas и файлом HelloWorldViewController.h в Assistant editor вы обновили файл реализации HelloWorldViewController.m, и теперь он поддерживает аутлеты и действия. Если хотите внимательнее изучить изменения в файле реализации, откройте его с помощью навигатора проекта.

Создавая связи путём перетаскивания из области canvas в исходный файл, у вас нет необходимости использовать возможности Xcode для автоматического добавления кода. Вместо этого вы самостоятельно добавляете в файл заголовка свойство и объявление метода, а после создаёте необходимые связи, как вы делали с делегатом текстового поля. Однако вы сделаете меньше ошибок, если позволите Xcode выполнять как можно больше работы автоматически.

Реализация View Controller

Для этого пройдем через несколько этапов: добавляем свойство для имени пользователя, реализуем метод changeGreeting: и проверяем, как работает функция скрытия клавиатуры после тапа по кнопке Done.

Добавление свойства для имени пользователя

Необходимо добавить объявление свойства для строки, содержащей имя пользователя, чтобы в коде всегда была ссылка на него. Добавим это объявление в файл заголовка view controller'а — HelloWorldViewController.h.

Объявление свойства — это директива, которая сообщает компилятору методы доступа к переменной, например переменной, используемой для хранения имени пользователя. (О методах доступа вы узнаете позднее, после того, как добавите объявление свойства.)

На данный момент вносить какие-либо изменения в файл storyboard не нужно. Чтобы освободить себе пространство для добавления кода, описанного ниже, скройте область утилит нажатием на кнопку Utilities View или выбрав View > Utilities > Hide Utilities

Чтобы добавить объявление свойства для имени пользователя необходимо:

  1. В навигаторе проекта выбрать HelloWorldViewController.h.
  2. Добавить оператор @property для строки перед оператором @end.

    Объявление свойства выглядит следующим образом:

    @property (copy, nonatomic) NSString *userName;

    Можете скопировать этот фрагмент кода или же ввести его вручную в панели редактора. Если вы решили ввести код вручную, обратите внимание на подсказки, предлагаемые Xcode. К примеру, если вы начнёте вводить @pro... Xcode предложит подсказку для @property:

    Если подсказка верная, нажмите Return.

    По мере ввода Xcode будет предлагать различные подсказки, из которых вы можете выбирать необходимые свойства. Например, если вы введёте NSSt..., то Xcode предложит вам следующий список подсказок на выбор:

    Для выбора подсказки (она будет подсвечена) нажмите Return. Если подсвеченная подсказка вам не подходит, используйте стрелки для выбора необходимой.

Чтобы закончить реализацию свойства userName, вам необходимо, чтобы компилятор синтезировал методы доступа. Метод доступа — это метод, который получает или же задаёт значение свойству объекта; в зависимости от назначения методы доступа могут называться «getters» и «setters».

Xcode выводит предупреждение об этом в виде жёлтого восклицательного знака:

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

В данном руководстве вы пишете код, который сообщает компилятору задачу по синтезированию методов доступа в файле реализации view controller'а HelloWorldViewController.m.

Для синтезирования методов доступа для свойства имени пользователя необходимо:

  1. В навигаторе проекта выбрать HelloWorldViewController.m.
  2. После строки @implementation HelloWorldViewController добавить следующий код:

    @synthesize userName = _userName;

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

Когда компилятор находит директиву @synthesize, он автоматически генерирует два метода доступа:

- (NSString *)userName

- (void)setUserName:(NSString *)newUserName

Добавляя нижнее подчёркивание к userName в строке кода @synthesize, вы сообщаете компилятору, что нужно использовать _userName как переменную экземпляра свойства userName. Поскольку вы не объявляли в используемом классе переменную экзмепляра _userName, компилятор синтезирует и её.

Обратите внимание: компилятор добавляет генерируемые методы доступа в компилируемый код, но не добавляет их в исходный код.

Реализация метода changeGreeting:

В настройке view вы настраивали кнопку «Hello» таким образом, чтобы при тапе она отправляла сообщение changeGreeting: во view controller. В ответ на это действие мы хотим, чтобы view controller отобразил в ярлыке текст, введённый пользователем в текстовое поле. Таким образом, метод changeGreeting: должен:

  1. Возвращать строку из текстового поля и устанавливать во view controller'е свойство userName для этой строки.
  2. Создавать новую строку на основе свойства userName и отображать её в ярлыке.

Для реализации метода changeGreeting: необходимо:

  1. При необходимости выбрать в навигаторе проекта HelloWorldViewController.m.

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

  2. Дополнить заготовку метода changeGreeting:, добавив в неё следующий код:

    - (IBAction)changeGreeting:(id)sender {

    self.userName = self.textField.text;

    NSString *nameString = self.userName;

    if ([nameString length] == 0) {

    nameString = @"World";

    }

    NSString *greeting = [[NSString alloc] initWithFormat:@"Hello, %@!", nameString];

    self.label.text = greeting;

    }

Несколько моментов в методе changeGreeting:, на которые стоит обратить внимание:

  • self.userName = self.textField.text; возвращает текст из текстового поля и выводит свойство userName в результат.

    В принципе, в данном руководстве вы больше нигде не используете строку с именем пользователя, но всё-таки необходимо запомнить её роль — это очень простая модель, управляемая view controller'ом. В целом, контроллер управляет информацией о данных приложения и моделях, данные приложения не должны храниться в UI-элементах, таких как текстовое поле приложения HelloWorld.

  • NSString *nameString = self.userName; создаёт новую переменную типа NSString и задаёт ей значение свойства userName во view controller'е.
  • @"World" — это строковая константа, представленная экземпляром NSString. Если пользователь запустит приложение, но не введёт текст (т.е. [nameString length] == 0), nameString будет содержать только строку «World».
  • Метод initWithFormat: предоставлен фреймворком Foundation. Он создаёт новую строку формата, указанного в форматной строке (принцип похож на функцию C printf, с которой вы, вероятно, знакомы).

    В форматной строке %@ выполняет функцию placeholder'а для строкового объекта. Все остальные символы внутри двойных кавычек в форматной строке будут отображаться на экране именно так, как они выглядят.

Настраиваем View Controller делегатом текстового поля

После того, как вы собрали и запустили приложение, вы увидите, что при клике на кнопку ярлык выводит «Hello, World!». Если вы кликните на текстовое поле и начнете печатать, то вы увидите, что все ещё нет способа скрыть клавиатуру.

В iOS приложениях клавиатура появляется автоматически, когда элемент, отвечающий за ввод текста, становится first responder'ом; и исчезает автоматически в тот момент, когда элемент теряет статус first responder'а.

Протокол UITextFieldDelegate определяется фреймворком UIKit и включает в себя метод textFieldShouldReturn:, вызываемый текстовым полем при тапе на Return (тут не имеет значения? как называется в данный момент кнопка Return: Done, Готово и т.п.). Так как делегатом текстового поля у нас назначен view controller, мы можем реализовать этот метод для того, чтобы текстовое поле теряло статус first responder'а (для этого используем сообщение resignFirstResponder) и, как следствие, клавиатура для ввода текст исчезала бы с экрана.

Обратите внимание: Протокол — это всего лишь список методов. Если класс удовлетворяет протоколу, то все обязательные методы реализованы. (Протокол также может включать в себя необязательные методы). Протокол делегата определяет все сообщения, отправляемые объектом делегату

Чтобы настроить HelloWorldViewController делегатом текстового поля необходимо:

  1. При необходимости выбрать в навигаторе проекта HelloWorldViewController.m.
  2. Реализовать метод textFieldShouldReturn:

    Этот метод будет сообщать текстовому полю об утрате им статуса first responder'а. Реализация будет выглядеть следующим образом:

    - (BOOL)textFieldShouldReturn:(UITextField *)theTextField {

    if (theTextField == self.textField) {

    [theTextField resignFirstResponder];

    }

    return YES;

    }

    В принципе, в этом приложении необязательно проверять theTextField == self.textField, поскольку в нашем приложении всего одно текстовое поле. Тем не менее это весьма полезный шаблон, т.к. могут возникать ситуации, когда объект является делегатом для нескольких объектов одного типа одновременно, и может возникнуть необходимость различать их между собой.

  3. В навигаторе проекта выберите HelloWorldViewController.h.
  4. В конце строки @interface добавьте <UITextFieldDelegate>.

    Объявление интерфейса должно выглядеть следующим образом:

    @interface HelloWorldViewController : UIViewController <UITextFieldDelegate> ...

    Это объявление определяет класс HelloWorldViewController, удовлетворяющий протоколу UITextFieldDelegate.

Тестирование приложения

Собираем и запускаем приложение. Теперь все должно работать именно так, как мы запланировали. В окне Simulator после ввода имени нажмите клавишу Done, чтобы скрыть клавиатуру и затем нажмите кнопку «Hello», чтобы увидеть в ярлыке «Hello, Your Name

Если же приложение работает некорректно, придётся исправлять допущенные ошибки. Об этом будет рассказано в главе «Исправление ошибок и анализ кода».

Итог

После того, как вы закончили реализацию view controller'а, можно сказать, что вы создали своё первое iOS приложение. Поздравляем!

Исправление ошибок и анализ кода

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

Код и предупреждения компилятора

Ваш код не должен содержать каких-либо предупреждений. Если же у вас есть значки предупреждений, то, вероятнее всего, ошибка кроется именно там. Objective-C считается довольно гибким языком, и иногда самое большее, что вы можете получить от компилятора, это значок предупреждения

Проверьте файл Storyboard

Будучи разработчиком вы должны привыкнуть к мысли, что если приложение не работает, то следует проверить исходный код на наличие ошибок. Однако, при использовании Cocoa Touch появляется ещё один нюанс. Большая часть конфигурации приложения может быть «зашифрована» в storyboard'е. К примеру, если вы создали связи неправильно, то приложение может работать не так, как вы того ожидаете.

  • Если при клике на кнопку у вас не обновляется текст, то, вероятно, вы не связали действие кнопки с view controller, либо не связали аутлеты view controller`a с текстовым полем и ярлыком.
  • Если у вас после клика по кнопке Done не исчезает клавиатура, то, вероятно, вы не связали делегат текстового поля либо связали аутлет view controller`а textField с текстовым полем. Проверьте все созданные для текстового поля связи в storyboard: Сделайте Control-клик на текстовом поле, чтобы увидеть панель созданных связей. Возле аутлета delegate и ссылающегося аутлета textField должны стоять отмеченные кружочки.

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

Именование методов делегата

Неправильно заданное имя метода делегата — одна из самых распространённых ошибок. Даже если вы правильно создали связи объекта делегата, но допустили ошибку в названии, то желаемый метод не может быть реализован. По этой причине лучше не вводить объявление методов делегата, а копировать их из документации.

Листинг кода

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

Файл интерфейса: HelloWorldViewController.h

#import

@interface HelloWorldViewController : UIViewController

@property (weak, nonatomic) IBOutlet UITextField *textField;

@property (weak, nonatomic) IBOutlet UILabel *label;

@property (nonatomic, copy) NSString *userName;

- (IBAction)changeGreeting:(id)sender;

@end

Файл реализации: HelloWorldViewController.m

#import "HelloWorldViewController.h"

@implementation HelloWorldViewController

@synthesize textField=_textField;

@synthesize label=_label;

@synthesize userName=_userName;

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {

if (theTextField == self.textField) {

[theTextField resignFirstResponder];

}

return YES;

}

- (IBAction)changeGreeting:(id)sender {

self.userName = self.textField.text;

NSString *nameString = self.userName;

if ([nameString length] == 0) {

nameString = @"World";

}

NSString *greeting = [[NSString alloc] initWithFormat:@"Hello, %@!", nameString];

self.label.text = greeting;

}

@end

Сайт: http://apple.com

Copyright: Apple

Комментариев нет:

Отправить комментарий