UIViewController внутри другого UIViewController или как работать с Container View

container_view_proswift_ru_fmekw

Недавно я делал приложение, в котором мне понадобилось использовать такой элемент интерфейса как Container View. Если этот элемент разместить на контроллере, то он создал еще один контроллер, который будет вписан в размеры Container View. С этим контроллером можно делать все что и с обыкновенным контроллером, только он будет вписан в другой контроллер. Мне нужно было передавать информацию из одного из родительского контроллера во вписанный, и я с удивлением обнаружил, что примеров использования с описанием процесса передачи информации крайне мало. Поэтому решил выложить здесь результаты своих экспериментов.

Постановка задачи

Наша задача создать приложение с тремя кнопками, по нажатию на которые в нижней части экрана будет заполнятся таблица различным содержанием. Таблица будет представлена отдельным UITableViewController, который мы впишем в Container View.

Создание приложения в Xcode

Откройте Xcode, выберите Single View Application

container_view_proswift_ru_f2ng3

Задайте имя и  место размещения проекта

container_view_proswift_ru_flg0a

Перейдите в Main Storyboard и из библиотеки элементов перенесите на контролер три кнопки. Я назвал кнопки «Имена», «Числа» и «Цвета», хотя это и не принципиально. Разместил из по центру контроллера и задал констрейнты таким образом, чтобы кнопки оставались в центре при любом положении и размере экрана.

container_view_proswift_ru_ggyw2

В нижнюю часть нашего контроллера из библиотеки элементов перетащите Container View и при помощи инструментов Auto Layout прикрепите  границы контейнера к границам контроллера.

container_view_proswift_ru_4dycq

Обратите внимание, при добавлении Container View Xcode создал еще один контроллер по размеру такой же как и размер контейнера.

Так как для выполнения поставленной задачи необходима таблица, нужно выбрать вновь созданный View Controller и удалить его.

container_view_proswift_ru_kfctl

Затем из библиотеки элементов перенесите в Main Storyboard Table View Controller.

container_view_proswift_ru_gxa2k

И последний этап приготовления заключается в том, чтобы вписать вновь добавленный контроллер в контейнер. Для этого ctrl-drag или правой кнопкой мыши перетащите указатель от Container View  к TableViewController и выберите Embed.

container_view_proswift_ru_5dh0c

Размеры табличного контроллера уменьшились до размера контейнера.

Выберете  Segue и задайте идентификатор для этого перехода. Я указал InfoSegue.

container_view_proswift_ru_zwoja

Этот идентификатор нам понадобится немного ниже.

Теперь нужно создать отдельный класс и файл контроллера для нашей таблица и присвоить этот класс в Storyboard.

File -> New file -> Cocoa Touch Class.  Имя можно задать любое. Я выбрал InfoTableViewController. Разумеется, наследоваться он должен от UITableViewController.

container_view_proswift_ru_9ancs

В Storyboard задайте контроллеру только что созданный класс.

container_view_proswift_ru_mpnb5

Также нужно задать идентификатор для ячейки таблицы. Я указал InfoCell.

container_view_proswift_ru_inh5p

И наконец не забудьте создать методы для обработки нажатия на кнопки.

container_view_proswift_ru_rolxo




Манипуляция с данными

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

Перейдите в файл класса InfoTableViewController и добавьте массив со строками, который будет моделью данных для таблицы.

В этом же файле добавьте/раскомментируйте/измените методы UITableViewDataSource.

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

Для тестирования в метод viewDidLoad()  добавтье строку с добавлением тестовых данных в массив модели.

Запустите проект и вы увидите приложение с набором тестовых данных.

container_view_proswift_ru_kylc4

Передача данных из основного контроллера в таблицу

Есть два варианта передачи данных из родительского контроллера в контроллер Container View.

Передача данных на этапе инициализации.

Как и для других контроллеров, контроллер в контейнере перед инициализацией вызывает метод prepare(for segue:)  у контроллера, который его отображает.  Поэтому в этом методе можно передать данные в массив для отображения.

Давайте разбирать на практике.

Перейдите в файл класса  ViewController и добавьте метод:

Давайте еще раз разберем что тут происходит.

Основной ViewController для отображения содержания Container View совершает переход segue к контроллеру InfoTableViewController. Это означает, что перед переходом вызывается метод prepare(for segue:), в котором мы можем получить доступ к контроллеру, в который совершается переход. После получения ссылки на этот контроллер, мы передаем массив с данными в массив модели таблицы.

Внимание! Для проверки работоспособности этой передачи информации не забудьте в классе InfoTableViewController в методе viewDidLoad() закомментировать строку с добавлением тестовых данных.

Запустите проект заново и посмотрите результат:

container_view_proswift_ru_mrmtr

Ну и наконец давайте запрограммируем передачу данных в таблицу по нажатию на кнопки.

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

Разберем эти три строки

  1. В массив data мы заносим данные, которые хотим передать в таблицу.
  2. Используя свойство childViewControllers нашего ViewController мы получаем доступ к массиву дочерних контроллеров. С учетом того, что в нашем случае он единственный, мы используем индекс [0] для получения ссылки на него.  И в свойство modelArray передаем массив data
  3. Факта передачи данных недостаточно. Таблица уже отображает данные, которые в нее были загружены при инициализации. Хоть в массиве модели уже присутствуют другие данные, их таблица не отобразит. Именно поэтому мы вызываем метод reloadData() у свойства tableView. В этом случае новые данные отобразятся.

Запустите проект и посмотрите результат.

container_view_proswift_ru_vflca

 

P.S.

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




Метки:
10 комментариев на “UIViewController внутри другого UIViewController или как работать с Container View
  1. Levan:

    Автор молодец! Очень интересно, я добавил в закладки

  2. Павел:

    Автор, красава, круто буду использовать в работе!

  3. Babka:

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

    • admin:

      Можно. Я допишу статью о распознавании голоса и Speech Kit и сделаю и Ваш пример.
      Если я правильно понял, то у Вас что-то типа опросника. И я не совсем понимаю, зачем для каждого вопроса использовать отдельный ViewController. Это можно, и с точки зрения эффективного использования памяти — нужно реализовать в одном контреллере. Тогда вопрос глобальной переменной решится сам собой.
      В любом случае, спасибо за идею для следующей статьи.

  4. Людмила Руссу:

    Спасибо, большое за статьи ) Очень помогают выбраться на берег из моря информации, после которой обычно в голове каша. Примеры кода с краткими и не уходящими в теорию объяснениями, отличный формат. Мои краеугольные камни: цикл жизни ViewController и его View, способы передачи данных между ViewController в разных задачах (segue, delegate), очереди-потоки т.ею распараллеливание задач в приложении (вот бы придумать сюжет с трехмерным иллюстрированием всех этих взаимодействий в iOS программировании), утечки памяти в Closure (лечение модификаторами ссылок weak, unown в зависмости от задачи), понимание взаbмосвязи между bounds, layer, frame … Хорошр было бы тренажер ещё по такмим задачам. И конечно есть ещё куча всего о чем я ещё и не слышала. Главное что я хотела сказать, это спасибо за ваш труд проводника к совершенствованию в программировании.

  5. Александр:

    File -> New file -> Cocoa Touch Class. Имя можно задать любое. Я выбрал InfoTableViewCintroller. Разуметтся, наследоваться он должен от UITableViewController.

    опечатка в InfoTableViewCintroller

Добавить комментарий для admin Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*