Подробный обзор примера приложения "Привет, iOS"

Краткое пошаговое руководство, описывающее создание и запуск простого приложения Xamarin.iOS. Пришло время подробнее изучить принципы работы приложений iOS, чтобы создавать более сложные программы. Это руководство описывает шаги, предпринятые в пошаговом руководстве "Привет, iOS", чтобы вы могли изучить основные принципы разработки приложений iOS.

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

Введение в Visual Studio для Mac

Visual Studio для Mac — это бесплатная интегрированная среда разработки (IDE) с открытым кодом, объединяющая в себе функции Visual Studio и Xcode. Она включает в себя полностью интегрированный визуальный конструктор, текстовый редактор с инструментами рефакторинга, обозреватель сборок, средства интеграции исходного кода и другие возможности. В этом руководстве описаны некоторые базовые функции Visual Studio для Mac, но если сталкиваетесь с Visual Studio для Mac впервые, обратитесь к документации о Visual Studio для Mac.

В Visual Studio для Mac, так же как в Visual Studio, код упорядочивается по решениям и проектам. Решение — это контейнер для одного или нескольких проектов. Проект может представлять собой приложение (например, для iOS или Android), вспомогательную библиотеку, тестовое приложение и т. д. В приложение Phoneword был добавлен новый проект iPhone с помощью шаблона Приложение одного представления. Исходное решение выглядело следующим образом:

Снимок экрана исходного решения

Введение в Visual Studio

Visual Studio — это полнофункциональная интегрированная среда разработки (IDE) от корпорации Майкрософт. Она включает в себя полностью интегрированный визуальный конструктор, текстовый редактор с инструментами рефакторинга, обозреватель сборок, средства интеграции исходного кода и другие возможности. Это руководство описывает, как использовать некоторые основные возможности Visual Studio с инструментами Xamarin для Visual Studio.

Код в Visual Studio упорядочен по решениям и проектам. Решение — это контейнер для одного или нескольких проектов. Проект может представлять собой приложение (например, для iOS или Android), вспомогательную библиотеку, тестовое приложение и т. д. В приложение Phoneword был добавлен новый проект iPhone с помощью шаблона Приложение одного представления. Исходное решение выглядело следующим образом:

Снимок экрана исходного решения

Структура приложения Xamarin.iOS

Слева находится Панель решения, которая содержит структуру каталогов и все файлы, связанные с решением:

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

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

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

В пошаговом руководстве Привет, iOS вы создали решение Phoneword и поместили внутрь него проект iOS — Phoneword_iOS. Ниже перечислены элементы, входящие в проект:

  • References — содержит сборки, необходимые для создания и запуска приложения. Разверните этот каталог, чтобы отобразить ссылки на сборки .NET, такие как System, System.Core и System.Xml, а также ссылку на сборку Xamarin.iOS.
  • Packages — каталог Packages содержит готовые пакеты NuGet.
  • Resources — в папке Resources хранятся другие файлы мультимедиа.
  • Main.cs — это файл содержит главную точку входа для приложения. Для запуска приложения имя главного класса приложения передается в AppDelegate.
  • AppDelegate.cs — этот файл содержит главный класс приложения и отвечает за создание окна, формирование пользовательского интерфейса и прослушивание событий из операционной системы.
  • Main.Storyboard — раскадровка содержит визуальную структуру для пользовательского интерфейса приложения. Файлы раскадровки открываются в графическом редакторе, называемом конструктором iOS.
  • ViewController.cs — контроллер представления обслуживает экран (представление), который пользователь просматривает и с которым взаимодействует. Контроллер представления отвечает за обработку взаимодействия между пользователем и представлением.
  • ViewController.designer.cs — designer.cs представляет собой автоматически созданный файл, который соединяет элементы управления в представлении и их представлениях кода в контроллере представления. Так как это файл для внутреннего подключения, интегрированная среда разработки перезаписывает любые внесенные вручную изменения, и в большинстве случаев этот файл можно игнорировать.
  • Info.plist — в Info.plist задаются свойства приложения, такие как имя приложения, значки, изображения запуска и другие. Этот файл предоставляет обширные возможности и подробно описан в руководстве Работа со списками свойств.
  • Entitlements.plist — список свойств назначений позволяет указать возможности приложения (так называемые технологии App Store), например iCloud, PassKit и многие другие. Дополнительные сведения о файле Entitlements.plist см. в руководстве Работа со списками свойств. Общие сведения о назначениях см. в руководстве Подготовка устройств.

Архитектура и принципы работы приложения

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

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

На этой схеме показаны связи архитектуры и принципов работы приложения

Метод Main

Главной точкой входа для приложения iOS является класс Application. Класс Application определен в файле Main.cs, который содержит статический метод Main. Он создает экземпляр приложения Xamarin.iOS и передает имя класса делегата приложения, который будет обрабатывать события операционной системы. Код шаблона для статического метода Main представлен ниже:

using System;
using UIKit;

namespace Phoneword_iOS
{
    public class Application
    {
        static void Main (string[] args)
        {
            UIApplication.Main (args, null, "AppDelegate");
        }
    }
}

Делегат приложения

В iOS класс делегата приложения обрабатывает системные события и располагается внутри AppDelegate.cs. Класс AppDelegate управляет окном приложения. Окно является отдельным экземпляром класса UIWindow, который служит контейнером для пользовательского интерфейса. По умолчанию приложение получает только одно окно для загрузки своего содержимого, и это окно подключено к экрану (отдельный экземпляр UIScreen), который предоставляет ограничивающий прямоугольник, соответствующий размерам экрана физического устройства.

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

Код шаблона для AppDelegate приведен ниже:

using System;
using Foundation;
using UIKit;

namespace Phoneword_iOS
{

    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        public override UIWindow Window {
            get;
            set;
        }

        ...
    }
}

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

Пользовательский интерфейс

Пользовательский интерфейс приложения iOS похож на онлайн-магазин — приложение обычно получает одно окно, но может заполнять его любым необходимым количеством объектов, а объекты и схемы упорядочения могут изменяться в зависимости от того, что приложение хочет отобразить. В этом сценарии объекты — то, что видит пользователь — называются представлениями. Чтобы создать один экран в приложении, представления располагаются друг над другом в виде иерархии представлений содержимого, а управляет такой иерархией отдельный контроллер представления. Приложения с несколькими экранами используют несколько иерархий представлений содержимого, каждая из которых имеет свой контроллер представления. Приложение размещает представления в окне, чтобы создать другую иерархию представлений содержимого в зависимости от экрана, на котором находится пользователь.

Дополнительные сведения о создании пользовательского интерфейса с помощью раскадровок см. в разделе "Проектирование с использованием раскадровок" в документации Обзор Xcode в библиотеке Apple для разработчиков iOS.

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

Связи между окном, представлениями, вложенными представлениями и контроллером представления

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

Контроллеры представлений и жизненный цикл представления

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

Контроллеры представлений и раскадровки

На раскадровке контроллер представлен полосой в нижней части сцены. При выборе контроллера представления его свойства отображаются на Панели свойств:

При выборе контроллера представления его свойства отображаются на Панели свойств

Пользовательский класс контроллера представления для иерархии представлений содержимого, представленный этой сценой, можно задать, изменяя свойство Класс в разделе Удостоверение на панели свойств. Например, наше приложение Phoneword задает ViewController в качестве контроллера представления для первого экрана, как показано на снимке экрана ниже:

Приложение Phoneword задает ViewController в качестве контроллера представления

На раскадровке контроллер представлен полосой в нижней части сцены. При выборе контроллера представления его свойства отображаются на панели свойств:

При выборе контроллера представления его свойства отображаются на Панели свойств

Пользовательский класс контроллера представления для иерархии представлений содержимого, представленный этой сценой, можно задать, изменяя свойство Класс в разделе Удостоверение на панели свойств. Например, наше приложение Phoneword задает ViewController в качестве контроллера представления для первого экрана, как показано на снимке экрана ниже:

Приложение Phoneword задает ViewController в качестве контроллера представления

Это связывает представление раскадровки контроллера представления с классом ViewController C#. Откройте файл ViewController.cs и обратите внимание, что контроллер представления является подклассом класса UIViewController, как показано в следующем коде:

public partial class ViewController : UIViewController
{
    public ViewController (IntPtr handle) : base (handle)
    {

    }
}

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

Примечание.

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

Жизненный цикл представления

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

Ниже представлены основные методы жизненного цикла и их функции:

  • ViewDidLoad — вызывается, когда контроллер представления впервые загружает свою иерархию представлений содержимого в память. Он хорошо подходит для первоначальной настройки, так как именно здесь вложенные представления впервые становятся доступными в коде.
  • ViewWillAppear — вызывается каждый раз, когда представление контроллера представления готовится к добавлению в иерархию представлений содержимого и отображается на экране.
  • ViewWillDisappear — вызывается каждый раз, когда представление контроллера представления готовится к удалению из иерархии представлений содержимого и пропадает с экрана. Это событие жизненного цикла используется для очистки и сохранения состояния.
  • ViewDidAppear и ViewDidDisappear — вызываются при добавлении представления в иерархию представлений содержимого и удалении его оттуда, соответственно.

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

Дополнительные сведения о работе с контроллерами представлений см. в руководстве по программированию контроллеров представлений для iOS и справочнике по UIViewController компании Apple.

Реакция на действия пользователя

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

Давайте посмотрим, как это работает. В проекте Phoneword_iOS в иерархию представлений содержимого была добавлена кнопка TranslateButton:

В иерархию представлений содержимого была добавлена кнопка TranslateButton

Если ссылочная переменная объекта создается с помощью Xcode Interface Builder, Xcode Sync автоматически сопоставит ее с элементом управления в ViewController.designer.cs, сделав объект TranslateButton доступным в классе ViewController. Впервые элементы управления становятся доступными на этапе ViewDidLoad жизненного цикла представления, поэтому этот метод жизненного цикла используется для реагирования на сенсорный ввод пользователя:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // wire up TranslateButton here
}

Приложение Phoneword использует событие сенсорного ввода TouchUpInside для прослушивания сенсорного ввода пользователя. TouchUpInside прослушивает событие отрыва пальца от экрана, а затем события прикосновения к экрану в границах элемента управления. Противоположностью TouchUpInside является событие TouchDown, которое возникает, когда пользователь нажимает элемент управления. Событие TouchDown перехватывает много посторонних данных и не позволяет пользователю отменить касание, отведя палец за границу элемента управления. TouchUpInside является наиболее распространенным способом для реагирования на касание кнопки и обеспечивает процедуру взаимодействия, ожидаемую пользователем при нажатии кнопки. Дополнительные сведения об этом доступны в рекомендациях по работе с человеческим интерфейсом iOS компании Apple.

Приложение обрабатывало событие TouchUpInside с помощью лямбда-выражения, но вместо этого можно было использовать делегат или именованный обработчик событий. В конечной форме код элемента "Button" выглядит так:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    string translatedNumber = "";

    TranslateButton.TouchUpInside += (object sender, EventArgs e) => {
      translatedNumber = Core.PhonewordTranslator.ToNumber(PhoneNumberText.Text);
      PhoneNumberText.ResignFirstResponder ();

      if (translatedNumber == "") {
        CallButton.SetTitle ("Call", UIControlState.Normal);
        CallButton.Enabled = false;
      } else {
        CallButton.SetTitle ("Call " + translatedNumber, UIControlState.Normal);
        CallButton.Enabled = true;
      }
  };
}

Дополнительные понятия, представленные в Phoneword

В приложении Phoneword представлено несколько понятий, не охваченных этим руководством. В их число входят следующие:

  • Изменение текста кнопки — приложение Phoneword продемонстрировало, как изменить текст элемента Button, вызвав SetTitle для Button и передав новый текст и состояние элемента управленияButton. Например, следующий код позволяет изменить текст CallButton на "Call" (Вызов):

    CallButton.SetTitle ("Call", UIControlState.Normal);
    
  • Включение и отключение кнопок — кнопки могут находиться в состоянии Enabled или Disabled. Отключенный элемент Button не реагирует на действия пользователя. Например, в следующем коде отключается объект CallButton:

    CallButton.Enabled = false;
    

    Дополнительные сведения о кнопках см. в руководстве Кнопки.

  • Убирание клавиатуры — когда пользователь касается текстового поля, iOS отображает клавиатуру, чтобы он мог ввести данные. К сожалению, встроенная функция для убирания клавиатуры отсутствует. Следующий код добавляется в TranslateButton, чтобы закрывать клавиатуру, когда пользователь нажимает TranslateButton:

    PhoneNumberText.ResignFirstResponder ();
    

    Еще один пример отмены клавиатуры см. в разделе Отмена клавиатуры.

  • Выполнение телефонного вызова с URL-адресом — в приложении Phoneword используется схема URL-адресов Apple для запуска приложения телефонной системы. Пользовательская схема URL-адресов состоит из префикса "tel:" и преобразованного телефонного номера, как показано в следующем коде:

    var url = new NSUrl ("tel:" + translatedNumber);
    if (!UIApplication.SharedApplication.OpenUrl (url))
    {
        // show alert Controller
    }
    
  • Отображение оповещения — когда пользователь пытается выполнить телефонный вызов на устройстве, которое не поддерживает такие вызовы, например, в симуляторе или на iPod Touch, отображается диалоговое окно, оповещающее пользователя о невозможности телефонного вызова. Приведенный ниже код создает и заполняет контроллер оповещения:

    if (!UIApplication.SharedApplication.OpenUrl (url)) {
                    var alert = UIAlertController.Create ("Not supported", "Scheme 'tel:' is not supported on this device", UIAlertControllerStyle.Alert);
                    alert.AddAction (UIAlertAction.Create ("Ok", UIAlertActionStyle.Default, null));
                    PresentViewController (alert, true, null);
                }
    

    Дополнительные сведения о представлениях оповещений iOS см. в инструкции по контроллеру оповещений.

Тестирование, развертывание и последние штрихи

Как Visual Studio для Mac, так и Visual Studio предоставляют множество возможностей для тестирования и развертывания приложения. В этом разделе рассматриваются возможности отладки, демонстрируется тестирование приложения на устройстве и представлены инструменты для создания пользовательских значков приложения и изображений при запуске.

Средства отладки

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

Развертывание на устройстве

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

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

Примечание.

Сейчас, в связи с требованиями Apple, при компиляции кода для физического устройства или симулятора требуется сертификат разработки или удостоверение подписывания. Чтобы настроить их, следуйте указаниям в руководстве по подготовке устройств.

После подготовки устройство можно развернуть, подключив его, изменив целевой объект в панели инструментов сборки на устройство iOS и нажав кнопку Запустить (Воспроизвести), как показано на следующем снимке экрана:

Нажатие кнопки

Нажатие кнопки

Приложение развертывается на устройстве iOS:

Приложение развертывается на устройстве iOS и запускается

Создание пользовательских значков и изображений, которые появляются при запуске

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

  • Pixelmator — универсальный редактор изображений для Mac, который стоит приблизительно 30 USD.
  • Fiverr — воспользуйтесь услугами одного из дизайнеров по созданию набора значков по цене от 5 USD. Результат может быть разным, однако это хороший ресурс, если вам нужно создать значки максимально быстро.
  • Visual Studio — создать простой набор значков для приложения можно непосредственно в интегрированной среде разработки.
  • Fiverr — воспользуйтесь услугами одного из дизайнеров по созданию набора значков по цене от 5 USD. Результат может быть разным, однако это хороший ресурс, если вам нужно создать значки максимально быстро.

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

Итоги

Поздравляем! Теперь у вас должно быть ясное понимание того, из каких компонентов состоит приложение Xamarin.iOS и какие инструменты нужны для его создания. В следующем руководстве из серии "Приступая к работе" вы расширите наше приложение, реализовав обработку нескольких экранов. При добавлении в приложение поддержки нескольких экранов вы реализуете контроллер навигации, узнаете о переходах раскадровки, а также познакомитесь с шаблоном "Модель — представление — контроллер" (MVC).