Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. iOS SDK
Code

Первые шаги с UIKit

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Learn iOS SDK Development From Scratch.
Exploring the Foundation Framework
Table View Basics

Russian (Pусский) translation by Liliya (you can also view the original English article)

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


Что такое структура UIKit?

В то время как платформа Foundation определяет классы, протоколы и функции для разработки под iOS и OS X, платформа UIKit предназначена исключительно для разработки под iOS. Это эквивалент Application Kit или платформы AppKit для разработки под OS X.

Как и Foundation, UIKit определяет классы, протоколы, функции, типы данных и константы. Он также добавляет дополнительные функциональные возможности к различным базовым классам, таким как NSObject, NSString и NSValue, благодаря использованию категорий Objective-C.

Категории Objective C - удобный способ добавить дополнительные методы к существующим классам без необходимости создавать подклассы. Прочтите этот урок от Aaron Crabtree, если вы хотите узнать больше о категориях Objective-C.

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


Новое начало

Запустите Xcode и создайте новый проект, выбрав New> Project ... в меню File. В разделе iOS слева выберите категорию Application. Из списка шаблонов проектов выберите шаблон Single View Application template.

Шаблон Single View Application содержит основные строительные блоки приложения iOS и поэтому является хорошим местом для начала нашего путешествия.

Назовите проект UIKit и введите название организации и идентификатор компании. Введите префикс класса, как я объяснял ранее в этой серии, и установите «Устройства» на iPhone.

Сообщите Xcode, где вы хотите сохранить новый проект, и убедитесь, что проект находится под контролем версий, установив флажок Create git repository on My Mac. Посетите эту статью для получения дополнительной информации о контроле версий и его преимуществах.


Файлы и папки

Мы узнали много нового с тех пор, как в прошлый раз создавали проект для iOS с нуля, поэтому неплохо было бы изучить различные файлы и папки нашего нового проекта, чтобы узнать, не звонят ли они в колокол.

В Project Navigator вы должны увидеть три папки в корне проекта;

  • Продукция
  • Структура
  • папка с именем вашего проекта, UIKit в этом примере
  • папка, имя которой заканчивается тестами, в данном примере UIKitTests

Давайте посмотрим на содержимое каждого из этих папок.

Продукция

Папка Products в настоящее время содержит два элемента. Первый элемент носит имя нашего проекта и имеет расширение .app. Имя второго элемента оканчивается на Tests и имеет расширение .xctest. Я не буду описывать юнит-тесты в этой серии, поэтому вы можете пока игнорировать второй пункт.

Папка Products содержит приложение или приложения, созданные проектом после компиляции исходного кода.

Вы заметили, что UIKit.app будет выделена красным цветом? Всякий раз, когда Xcode не может найти файл, он выделяет файл красным цветом. Поскольку проект еще не скомпилирован, Xcode еще не создал продукт.

Структура

Папка Frameworks содержит рамки, с которыми связан проект. В предыдущей статье наш проект был связан только со структурой Foundation. Этот проект, однако, основан на шаблоне приложения iOS и поэтому связан с четырьмя структурами: Foundation, UIKit, Core Graphics и XCTest.

Возможно, вы помните базовую графическую платформу из этой серии. Каркас содержит интерфейсы для API-интерфейса (Quartz) 2D-рисования. Фреймворк XCTest связан с модульным тестированием, о котором я не буду рассказывать в этой серии.

В нашем проекте есть еще одно место, которое определяет, с какими структурами связан проект. Выберите свой проект в Project Navigator, выберите единственный элемент в разделе Targets  слева и откройте вкладку Build Phases вверху.

Открыв ящик Link Binary with Libraries, вы получаете тот же список структур, который мы видели в папке Frameworks. Связать наш проект с другой системной платформой iOS так же просто, как нажать кнопку «плюс» внизу списка и выбрать платформу из списка.

Папка проекта

Большая часть вашего времени проводится в папке проекта, которая в настоящее время содержит шесть файлов и одну папку с именем Supporting Files. Давайте начнем с рассмотрения содержимого папки «Вспомогательные файлы».

  • <PROJECT>-Info.plist: Этот файл, обычно называемый файлом проекта «info-dot-plist», представляет собой список свойств, который содержит различные параметры конфигурации. GeneralБольшинство этих параметров также можно изменить, выбрав проект в Project Navigator, выбрав цель в списке Targets и открыв вкладки GeneralCapabilities и Infotabs.
  • InfoPlist.strings: Если Info.plist содержит значения, которые необходимо локализовать, вы можете сделать это, указав их в InfoPlist.strings. Локализация приложений - это то, что мы не рассмотрим в этой серии.
  • main.m: Этот файл должен быть уже знаком. Однако при создании приложений для iOS вы редко изменяете содержимое main.m. Он содержит основную функцию main приложения, с которой начинается вся магия. Даже если мы не будем изменять main.m, это важно для вашего iOS-приложения.
  • <PROJECT>-Prefix.pch: Это предварительно скомпилированный заголовочный файл проекта, с которым мы уже сталкивались ранее в этой серии. Как следует из названия, файлы заголовков, перечисленные в предварительно скомпилированном файле заголовков, предварительно скомпилированы Xcode, что сокращает время, необходимое для компиляции вашего проекта. Структуры Foundation и UIKit меняются не очень часто, поэтому нет необходимости их компилировать каждый раз, когда вы компилируете свой проект. В дополнение к предварительной компиляции заголовочных файлов, перечисленных в предварительно скомпилированном заголовочном файле, каждый исходный файл в вашем проекте имеет префикс перечисленных заголовочных файлов.

Компоненты приложения

Теперь, когда мы знаем, для чего предназначены различные файлы и папки в нашем проекте, пришло время изучить различные компоненты приложения для iOS. Продолжая наше путешествие, мы столкнемся с несколькими классами, которые принадлежат UIKit. Каждый класс, принадлежащий платформе UIKit, начинается с префикса класса UI. Помните, что базовые классы имеют префикс NS.


 Model-View-Controller Pattern

Прежде чем мы начнем исследовать инфраструктуру UIKit, я хочу поговорить об образце Model-View-Controller (MVC). Шаблон MVC является одним из самых распространенных шаблонов в объектно-ориентированном программировании. Он способствует повторному использованию кода и имеет тесные связи с концепцией разделения обязанностей или интересов. Одной из основных целей шаблона MVC является отделение бизнес-логики приложения от уровня представления.

Cocoa Touch охватывает шаблон MVC, и поэтому важно понимать, что это такое и как оно работает. Другими словами, понимая шаблон MVC, будет намного легче понять, как различные компоненты приложения iOS работают вместе.

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

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

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


UIApplication

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

Когда приложение запускается, создается синглтон этого класса. Вы помните, что такое singleton object? Это означает, что только один экземпляр объекта класса UIApplication создается в течение времени жизни приложения.

Экземпляр UIApplication является точкой входа для взаимодействия с пользователем и отправляет события соответствующим целевым объектам. Точный смысл этого станет ясен через несколько минут, когда мы посмотрим на контроллеры представления.

В большинстве приложений iOS экземпляр UIApplication имеет связанный с ним объект делегата. Всякий раз, когда вы создаете проект iOS, используя один из предоставленных шаблонов, XCode создаст класс делегата приложения для вас. Посмотрите на имена исходных файлов в папке проекта в Project Navigator. Первые два файла называются TSPAppDelegate.

Экземпляр этого класса является делегатом синглтона UIApplication. Прежде чем более внимательно взглянуть на класс TSPAppDelegate, нам нужно понять, что такое шаблон делегата.

Ole Begemann написал отличную статью о последовательности запуска типичного приложения для iOS. В этой статье он рассказывает о различных задействованных компонентах и ​​их роли во время запуска приложения. Я настоятельно рекомендую прочитать эту статью, если вы хотите лучше понять роль класса UIApplication, а также таинственную функцию main() в main.m.


Шаблон делегата

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

Как и шаблон MVC, делегирование является распространенным в объектно-ориентированном программировании. Однако шаблон делегата в Cocoa Touch немного отличается, потому что он использует протокол делегата для определения поведения объекта делегата.

Давайте прыгнем вперед и посмотрим на таблицы. Если вы провели какое-то время с iPhone или iPad, то класс UITableView должен быть вам знаком. Он представляет упорядоченный список данных пользователю и выполняет эту работу очень хорошо.

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

Табличное представление передает эту ответственность на объект делегата. Иначе говоря, он делегирует эту задачу на другой объект, объект делегата. Потратьте немного времени, чтобы проверить ссылку на класс UITableView. У этого есть два свойства, названные dataSource и delegate. delegate уведомляется табличным представлением всякий раз, когда пользователь касается строки. Ответственность за реагирование на нажатие пользователя возлагается на объект делегата.

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

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

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


Приложение делегат

Теперь, когда мы знаем, что такое делегирование, пришло время изучить класс TSPAppDelegate, который Xcode создал для нас. При запуске приложения приложение создает экземпляр класса TSPAppDelegate. Обычно вам никогда не требуется явно создавать экземпляр объекта делегата приложения.

Откройте файл заголовка класса TSPAppDelegate (TSPAppDelegate.h), чтобы проверить его содержимое. Если мы проигнорируем комментарии вверху, первая строка импортирует заголовочные файлы инфраструктуры UIKit, чтобы мы могли работать с ее классами и протоколами.

Следующая строка должна быть знакомой. Это начало интерфейса класса TSPAppDelegate, как обозначено директивой @interface. Он определяет имя класса и суперкласс класса, UIResponder.

Между угловыми скобками указаны протоколы, которым соответствует класс. Класс TSPAppDelegate соответствует одному протоколу, протоколу UIApplicationDelegate.

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

Наиболее интересной частью интерфейса класса TSPAppDelegate является протокол UIApplicationDelegate. Взгляните на ссылку протокола UIApplicationDelegate для полного списка методов, определенных протоколом.

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

Когда экземпляр UIApplication завершит подготовку приложения к запуску, он уведомит делегата, наш экземпляр TSPAppDelegate, о том, что приложение завершит запуск, но пока этого не произошло.

Почему он уведомляет делегата приложения об этом событии? Экземпляр UIApplication уведомляет своего делегата об этом событии, чтобы у него была возможность подготовиться к запуску приложения. Перейдите к файлу реализации TSPAppDelegate, чтобы понять, что я имею в виду. Первый метод в файле реализации - это application:didFinishLaunchingWithOptions: и он должен более или менее выглядеть так, как показано ниже.

Метод application:didFinishLaunchingWithOptions: предоставляет ссылку на экземпляр UIApplication и словарь с параметрами, которые на данный момент нам не интересны. Реализация метода довольно проста. Все, что он делает - возвращает YES, чтобы сообщить экземпляру UIApplication, что приложение готово к запуску.

Раскадровка

Проект Xcode содержит еще один интересный файл, Main.storyboard. Раскадровка определяет, как будет выглядеть пользовательский интерфейс нашего приложения. По умолчанию раскадровка называется Main.storyboard. Выберите раскадровку, чтобы открыть ее.

В настоящее время раскадровка содержит один вид в центральной рабочей области. Справа от Project Navigator вы можете увидеть список элементов, которые являются объектами, которые вы видите в представлении. Верхний элемент называется View Controller Scene, который содержит один дочерний элемент, помеченный View Controller.

Объект View Controller также имеет несколько дочерних элементов, но есть один, который представляет для нас особый интерес, объект с именем View. Помните наше обсуждение образца MVC. Здесь вы можете увидеть шаблон MVC в действии. В данный момент модель отсутствует, но у нас есть представление, объект View и контроллер, объект View Controller.

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

Подожди минутку. Где я могу найти класс контроллера представления в раскадровке? Как я могу изменить его поведение, чтобы создать уникальное приложение? Выберите объект View Controller слева в раскадровке и откройте Identity Inspector справа.

Identity Inspector расскажет вам все, что вам нужно знать. расскажет вам все, что вам нужно знать. Вверху, в разделе Custom Class, вы можете увидеть имя класса контроллера представления, TSPViewController. Вы заметили, что два файла, о которых мы еще не говорили, имеют одно и то же имя? Мы рассмотрим эти файлы через несколько минут.

Мы рассмотрим эти файлы через несколько минут. Это указано в раскадровке стрелкой, указывающей на раскадровку.

UIViewController

Если вы откроете TSPViewController.h, вы заметите, что класс TSPViewController является подклассом UIViewController. Как и TSPAppDelegate, класс UIViewController является подклассом UIResponder. Контроллеры представления или их подклассы попадают в категорию контроллеров шаблона MVC. Как следует из названия, они управляют представлением, экземпляром класса UIView, который попадает в категорию представлений шаблона MVC.

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

Контроллер представления в раскадровке имеет ссылку на представление. +В этом можно убедиться, выбрав контроллер представления в раскадровке и открыв Connections Inspector справа.

В Connections Inspector вы должны увидеть раздел Outlets. Термин «аутлет» - это модное слово для свойства, которое вы можете задать в раскадровке. Наведите указатель мыши на розетку с именем view и посмотрите, как подсвечивается представление в рабочей области. Это связь между контроллером представления и представлением.


UIView

Даже если ваше приложение может иметь только один экземпляр UIWindow, оно может иметь много представлений. Класс UIView является важным компонентом инфраструктуры UIKit, потому что многие классы наследуют его - прямо или косвенно.

Пересмотрите Main.storyboard, выбрав его, и посмотрите на Object Library в нижней части Inspector.

Просмотрите библиотеку объектов и перетащите метку и кнопку в представление в рабочей области. Неважно, где вы размещаете их в представлении, пока они находятся в представлении контроллера представления.

Вы заметили, что два новых объекта были добавлены в раздел Objects слева. Метка (UILabel) и кнопку (UIButton) наследуют от UIView. Вы заметили, что объекты Label и Button имеют небольшой отступ по сравнению с объектом View? Это указывает на то, что объекты Label и Button являются под представлениями объекта View. Представление может иметь одно или несколько под представлений, которыми оно управляет.

Как я упоминал ранее, класс UIView является важным компонентом UIKit. Представление управляет прямоугольной областью или рамкой на экране. Он управляет содержимым области, под представлениями и любым взаимодействием с содержимым представления. Класс UIView является подклассом UIResponder. Вы узнаете намного больше о взглядах в течение этой серии.


Outlets

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

Несколько минут назад вы добавили метку и кнопку к представлению контроллера представления. Как контроллер представления узнает об этих объектах? На данный момент они не отображаются в Connections Inspector, но мы можем изменить это, сообщив о них контроллеру представления.

Откройте файл заголовка контроллера представления (TPSViewController.h) и добавьте свойство для метки и для кнопки.

Добавив ключевое слово IBOutlet в объявление свойства, свойства появятся в инспекторе соединений в раскадровке, и это то, что нам нужно.

Вернитесь к раскадровке, выберите объект View Controller в View Controller Scene и откройте Connections Inspector справа. Новые свойства теперь перечислены в списке Outlets. Однако контроллер представления еще не установил связь между новыми свойствами и объектами в раскадровке.

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


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

Откройте файл реализации контроллера представления (TPSViewController.m) и искать метод viewDidLoad. Измените метод viewDidLoad, чтобы отразить реализацию ниже. Комментарии были опущены для ясности.

Мы можем отправлять сообщения свойству label, запрашивая у view-контроллера self свойство myLabel. Отправляя свойству myLabel сообщение setText: и передавая строковый литерал, мы обновляем текст метки.

Обратите внимание, что setText: является аксессором или сеттером. Несмотря на то, что можно использовать точечную нотацию Objective-C (см. Ниже), я использовал более традиционный синтаксис, поскольку он лучше показывает вам, что на самом деле происходит.

Запустите приложение в iOS Simulator, нажав кнопку Run в левом верхнем углу, и обратите внимание, что текст метки действительно обновлен.


Поведение

В этой статье мы исследовали много нового. Я хочу закончить эту часть темы о действиях. Как и в случае с outlets, действия - это не что иное, как методы, которые вы можете увидеть в раскадровке.

Посмотрим, как это работает. Откройте файл заголовка контроллера представления (TPSViewController.h) и добавьте следующее объявление метода где-нибудь в блоке интерфейса контроллера представления.

Не смущайтесь ключевым словом IBAction. IBAction идентичен void, что означает, что метод не возвращает значения. Если мы более внимательно посмотрим на объявление метода, то увидим, что он принимает один аргумент типа id, ссылку на объект Objective-C.

Как следует из имени аргумента, аргумент метода или действия - это объект, который отправил сообщение в контроллер представления. Я объясню это немного подробнее.

Еще раз зайдите в раскадровку, выберите объект View Controller в сцене View Controller и откройте Connections Inspector. В Connections Inspector появился новый раздел под названием Received Actions, и только что добавленное действие перечислено в этом разделе.

Перетащите из пустого круга слева от действия на кнопку в рабочей области. Должно появиться небольшое окно со списком параметров. Список содержит все возможные события, на которые может ответить кнопка. То, что нас интересует, это Touch Up Inside. Это событие вызывается, когда пользователь касается кнопки и поднимает палец, нажимая на кнопку.

Создайте и запустите приложение еще раз и нажмите кнопку. Приложение пропало и у вас? Как это случилось? Когда вы нажали кнопку, он отправил сообщение changeColor: в контроллер представления. Хотя контроллер представления объявляет метод changeColor:, он еще не реализует этот метод.

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

Чтобы исправить это, нам нужно реализовать метод changeColor :. Откройте файл реализации контроллера представления (TPSViewController.m) и добавить следующую реализацию метода где-нибудь в блоке реализации.

Реализация метода changeColor: идентична той, которую мы использовали ранее в этой серии. Тем не менее, я добавил два дополнительных вызова NSLog к его реализации, чтобы показать вам, что отправитель сообщения действительно является кнопкой, которую мы добавили в раскадровку.

Сам метод довольно прост. Мы генерируем три случайных целых числа от 0 до 255, передаем эти значения в colorWithRed:green:blue:alpha: для генерации случайного цвета и обновляем цвет фона представления контроллера представления случайным образом сгенерированным цветом.

Обратите внимание, что self.view ссылается на представление, которым управляет контроллер представления и которое мы видели ранее в раскадровке.

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


Заключение

В этой статье мы рассмотрели несколько классов UIKit-структуру и подробно рассмотрели различные компоненты приложения для iOS. Мы будем исследовать и работать со  структурой UIKit более подробно в оставшейся части этой серии.

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

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.