Popover Controller на iPhone – пример создания из кода. ч.2

В первой части данного урока мы создали проект XCode, добавили файлы и классы для наших popover контроллеров, разместили контроллеры на Storyboard, добавили элементы интерфейса, с которыми будем работать и создали outlet’ы к ним. Т.е. сделали всю подготовительную работу — первые два пункта нашего плана.

В этой части урока  мы будем только писать код.

Вернее, сначала мы все-таки «нарисуем»  вызов  popoverController  в storyboard, а затем напишем все что нам надо…

Перейдите в Interface Builder — т.е. кликните на файл Main.Storyboard.

fileList_popver_proSwift

 

В нем сделайте ctrl-перетягивание от кнопки «Зеленый» до PopVC контроллера. В открывшемся меню нужно выбрать пункт «Present As Popover»

ctrl_drag_popver_proSwift

Появится Segue со значком popver. Далее нужно выбрать этот Segue  и в инспекторе атрибутов задать ему идентификатор. Я установил «ppcs». Нужно запомнить этот идентификатор, потому что мы будем использовать его для определения перехода и презентации popover контроллера.

1stID_popver_proSwift

В класс ViewController сразу после метода didReciveMemoryWarning() добавьте следующий код:

При совершении перехода (Segue) происходит вызов метода prepareForSegue. Наша задача обработать именно наш переход. Для этого мы и будем использовать идентификатор, который вводили ранее.

  1. Проверяем идентификатор перехода и если он совпадает с нашим — выполняем дальнейший код.
  2. Получаем контроллер в который происходит переход с помощью свойства destinationViewController  и пытаемся привести его к классу PopVC. Если нам это удается, а нам это удается, потому что нет другого перехода с искомым в п.1 идентификатором, то выполняем пункт 3
  3. Проверяем может ли контроллер, в который мы переходим быть представленный как popover и если может, то устанавливаем в качестве делегата self т.е. ViewController (наш корневой контроллер с серым фоном)

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

Swift позволяет это сделать в качестве расширения (extension) для класса, и рекомендую делать это именно так для читабельности кода и сохранения его структуры.

В файл ViewController.swift ПОСЛЕ (НЕ ВНУТРИ) реализации класса нужно добавить следующий код:

Тут мы сообщили компилятору,  что класс ViewController соответствует протоколу UIPopoverPresentationControllerDelegate и реализовали метод этого протокола adaptivePresentationStyleForPresentationController:

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

 green_popover_proswift

Наш контроллер заработал и показал зеленый popover. Пока не обращайте внимание на размеры контроллера и на точку, на которую указывает стрелка — в данном случае она указывает на точку с координатами (0,0) в системе координат view кнопки «Зеленый».

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

И для начала нужно задать идентификатор для голубого контроллера, чтобы получить ссылку на него из Storyboard.

2ndID_popver_proSwift

Я задал идентификатор «FromVTppc»

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

Измените метод viewDidLoad класса ViewController, чтобы он выглядел следующим образом:

Мы создали экземпляр класса UITapGestureRecognizer, который у нашего класса ViewController (self) будет вызывать метод tapHandler:, в момент когда жест буде распознан. Как вы понимаете, жест этот — это тап.  Затем мы добавляем экземпляр этого класса на наше blueView.

Теперь нужно реализовать метод tapHandler:. Можно просто добавить этот метод в класс ViewController, но я опять рекомендую сделать расширение класса.

После расширения соответствия протоколу добавьте следующее расширение, в котором будет описан метод tapHandler:

В нашем случае голубой контроллер создан в Storyboard и нам нужно показать его как popover.

  1. Получаем ссылку на наш Storyboard
  2. Получаем контроллер из storyboard с идентификатором «FromVTppc» и приводим его к классу FromViewTapPPC
  3. Полученному контроллеру задаем стиль модальной презентации popover
  4. Проверяем может ли полученный контроллер быть представленный как popover. и если может, то …
  5. Устанавливаем в качестве делегата self т.е ViewController
  6. Задаем разрешение показывать стрелки popover в любом направлении
  7. И обязательно указываем источник, на который эта стрелка будет показывать.
  8. Выводим на экран наш контроллер.

Класс ViewController уже соответствует протоколу  UIPopoverPresentationControllerDelegate, поэтому вопросов у компилятора не возникнет.

Запустите проект и понажимайте  на синее view

blue_popover_proswift

 

Оба контроллера работают, но стрелка голубого указывает немного неверно. Скоро мы и это поправим. Но чуть позже…

А сейчас давайте попробуем передать сообщение из нашего ViewController в FromViewTapPPC. Сделать это очень просто — все подготовительные работы мы проделали в первой части урока. Теперь надо установить нужное нам сообщение в свойство «name» экземпляра класса FromViewTapPPC. Добавьте следующую строку прямо перед presentViewController(fvtppc, animated: true, completion: nil)

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

Запустите проект и нажмите  на синее view.

demo2_full_popver_proSwift

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

Для начала исправим зеленый: в нем статическое сообщение и значит размер ему можно задать вполне определенный. Для этого в реализацию класса PopVC нужно добавить свойство preferredContentSize. Измените реализацию этого класса на следующую:

В данном случае мы задали вполне конкретный размер для зеленого popover. 360х180

Для синего контроллера ситуация немного другая — нужно определить размер содержимого в контроллере и исходя из этого размера вычислить размер самого контроллера. Замените реализацию класса на следующую:

Думаю, по коду все понятно. В size мы получили размер, в который вписывается label и для эстетичности добавили 30 по ширине и 60 по высоте.  Почему именно эти цифры? Они были получены методом подбора — я добавлял в размер различные значения и смотрел как будет красивее.

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

sized_mes_g_b_popover_proswift

Последнее, с чем нам осталось разобраться это с местом, в которое указывает стрелочка popover контроллера. Как было сказано выше стрелочка зеленого контроллера указывает на точку с координатами (0.0) того view, которое его вызвало. Мы нарисовали вызов от кнопки «Зеленый» значит стрелка будет указывать в левый верхний угол этой кнопки.

Стрелка голубого указывает приблизительно туда же, и это в корне не правильно. Давайте поменяем стрелку для голубого контроллера. сразу после строки  ppc.sourceView = tap.view нужно добавить вот эту строку:

В ней мы просим наш popover показывать стрелку на прямоугольник 1х1 в центре синего view. Можем запустить проект и посмотреть изменения:

demo6_sized_start_popver_proSwift

Можно было бы и так оставить проект, но можно сделать его еще более совершенным. Я имею ввиду, что мы можем указывать стрелку в то место синего view, куда тапнул пользователь. У нас для этого все есть, не нужно получать никаких дополнительных данных. Т.к. для обработки нажатия используется распознаватель жестов UITapGestureRecognizer координаты нажатия содержатся в нем. Нам нужно толко взять их и передать в  свойство  sourceRect.

Закоментируйте строку с sourceRect и вместо нее напишите вот этот код:

После компиляции проекта голубой контроллер работает очень хорошо.

demo4_sized_popver_proSwift

На этом все, уважаемые читатели.

Ссылка на gitHub: https://github.com/Ironrnd/popoverVC

Также оставлю исходный код файлов проекта ниже по тексту.

ViewController.swift:

FromViewTapPPC.swift

PopVC.swift

 

Опубликовано в Реальные примеры, Уроки, Элементы UI Метки:
2 комментария на “Popover Controller на iPhone – пример создания из кода. ч.2
  1. Юрий:

    Спасибо автору. Хороший материал для новичков.
    Но вот название переменных и идентификаторов… меня если често начинает трясти, когда я вижу подобные названия в виде аббревиатур (fvtppc, size20 — почему 20), ppc)

    • admin:

      Спасибо, Юрий!
      А по поводу имен — тут даже немного смешно вышло…
      fvtppc — это легко — при написании я имел ввиду From View Tap Popover Controller. А вот про size20 — пришлось лезть в код и вспоминать. И не получилось с ходу вспомнить! Но когда я залез в предыдущие версии проекта, то сразу вспомнил, что у меня там был CGRect 20х20 который в более поздних версиях поменял свой размер.

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

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

      И вот еще проблема — я так и не смог победить Refractor в XCode со всеми его функциями, в.т.ч. изменение имен переменных. XCode мне говорит, что он может рефракторить только код Objective-C, а Swift ему не подвластен. Может кто сталкивался и решил проблему — подскажите.

Добавить комментарий

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

*