Это решение Задания 3 — дополнительные пункты 4, 5 и 6. Обязательные пункты Задания, дополнительные пункты 1, 2 и 3, а также ссылки на текст самого Задания 3 можно посмотреть здесь:
Задание 3. Решение — обязательные пункты.
Задание 3. Решение — дополнительные пункты 1, 2 и 3.
Для окончательного решения код для Swift 1.2 находится на Github. Для Swift 2.0 код можно посмотреть на Github.
Пункт 4 дополнительный
При вращении прибора (или другом измении границ (bounds) ), разместите origin вашего графика по отношению к центру графического View, а не по отношению к верхнему левому углу.
Давайте рассмотрим класс GraphView нашего обобщенного пользовательского View, которое строит графики. Определим еще одно public свойство в этом классе
Это практически полная синтаксическая копия предыдущего свойства origin, но семантический смысл у него другой — это смещение начала координат графика по отношению к центру нашего пользовательского View. Свойство originRelativeToCenter хорошо тем, что его значение по умолчанию равно CGPointZero и не зависит от геометрии View. Мы можем задать его даже на этапе, когда «геометрия» нашего пользовательского View не определена.
Предыдущее public свойство origin, означающее смещение начала координат графика по отношению к левому верхнему углу нашего пользовательского View, остается, так как именно на него настроено рисование осей координат и самого графика. Но оно становится вычисляемым свойством на основе originRelativeToCenter
Заметьте, что для вычисления origin понадобится центр graphCenter нашего View, то есть геометрия должна быть уже определена к моменту использования origin. Действительно, origin будет запрашиваться только в функции drawInRect, которая существенно упростилась и в которой уже все outlets установлены, и согласно подсказке №8 Задания 3, геометрия полностью определена. Следовательно, никаких проблем с использованием origin у нас не будет.
Определенное заново вычисляемое свойство origin лучше сделать в классе GraphView private. У меня этого нет в текущем коде, но в окончательном варианте оно установлено как private. Вы можете сделать это сейчас. Во внешнем «мире», например, в классе GraphViewController, будем оперировать с originRelativeToCenter. Значение именно этого свойство будем запоминать в NSUserDefaults и восстанавливать из NSUserDefaults. Эти манипуляции мы производим в другом классе GraphViewController, классе нашего Controller. Этим будет заниматься private вычисляемая переменная originRelative (немного другое название, чем в классе GraphView).
Когда мы используем originRelative переменную в правой части выражения {get}, то вы «достаем» данные из NSUserDefaults, а когда в левой {set}— «записываем» данные в NSUserDefaults.
Нам нужно «достать» из NSUserDefaults координаты начала координат графика относительно центра сразу после загрузки outlet со storyboard. У нас один outlet — это обобщенный (generic) график graphView: GraphView! и в Наблюдателе Свойства этого автоматически подгружаемого со storyboard свойства, мы устанавливаем значение свойству originRelativeToCenter нашему графику, то есть используем originRelative переменную в правой части выражения.
Теперь посмотрим, где мы записываем начало координат графика относительно центра в NSUserDefaults. Его значение может измениться при использовании жестов panning и double-tapping (обязательный 11 пункт Задания 3). Запоминать в NSUserDefaults значение начало координат графика будем в методе «жизненного цикла» ViewWillDisappear нашего Controller
Здесь мы используем originRelative переменную в левой части выражения, следовательно идет «запись» в NSUserDefaults.
Код получился простой и понятный.Теперь, если начало координат графика находится близко к центру, то при автовращении прибора, мы также получим начало координат близко к центру.
Это будет выполняться системой автоматически при соответствующем определении возможных положений прибора в установках проекта
Код для Swift 1.2 находится на Github. Полное решение для Swift 2.0 можно посмотреть на Github.
Пункт 5 дополнительный
Добавьте Popover к вашему новому MVC, который будет сообщать о минимальном и максимальном y-значениях (и еще какую-нибудь статистику, если хотите) в области графика, показываемого в данный момент. Это потребует от вас создание еще одного MVC и segue к нему, используя popover segue. Это также потребует некоторого нового public API в вашем generic графическом View для предоставления статистики об области, в которой нарисован график.
Создаем специальную структуру Statistics для работы со статистикой, в которую включим расчет количества точек num, минимальное значение min, максимальное значение max и среднее значение avg. Эта структура инициализируются c нулевыми свойствами и имеет mutating метод calculate (y:CGFloat), который рассчитывает статистические параметры по мере поступления значений y. Структура Statistics позволяет представить себя ввиде строки с помощью протокола Printable и его свойства description.
Добавляем в класс GraphView public свойство, соответствующее экземпляру этой структуры
Методы этого экземпляра используем при построении графика в drawCurveInRect. Нам понадобится всего две строки.
Теперь у нас есть данные, которые мы должны отобразить в Popover. Popover не является самостоятельным View Controller, а служит для представления произвольного View Controller в виде Popover. Таким View Controller может быть фрагмент Text View Controller со storyboard из демонстрационного примера «Psychologist Popover» в Лекции 7. Можно скопировать из демонстрационного примера вначале файл TextViewController.swift, а затем сам фрагмент storyboard Text View Controller. Добавляем на MVC нашего графика кнопку (Bar Button Item) «Statistics«, соединяем ее с только что скопированным фрагментом Text View Controller с помощью segue типа popover presentation и даем ему имя «Show Statistics«.
Для отображения статистических параметров создаем специализированный subclass нашего более общего GraphViewController, имеющий имя StatisticsGraphViewController. Этот новый класс подверждает протокол делегата для Popover презентации с целью подавления адаптивного поведения Popover на приборах с горизонтальным размером .Compact. Об этом можно посмотреть специальный пост.
Нажатие кнопки «Statistics» вызывает появление Popover со статистическими данными о графике, находящемся на экране. Popover имеет вид «маленького окошка» на всех приборах, а также в портретном и ландшафтном режимах.
Код для Swift 1.2 находится на Github. Полное решение для Swift 2.0 можно посмотреть на Github.
Пункт 6 дополнительный
Сделайте калькулятор, который реагирует на изменение size class путем совершенно различного расположения элементов на пользовательском интерфейсе в среде различных size class (например, кнопок в различной сетке или даже добавлением различного количества операций в одном или другом size class). Когда вы делаете это, то ничего не должно ломаться!
Интерфейс в size классе Any-Any изменен: добавлены математические операции, кнопка построения графиков включена в клавиатуру калькулятора.
Количество столбцов по горизонтали — 5, а по вертикали — 7.
Интерфейс для size класса Any-Compact содержит по горизонтали 6 столбцов, а по вертикали — 6 строк.
Кроме того в этом режиме пришлось поменять фонт для операций, содержащих 4 буквы: asin, acos, atan, так как на iPone 6+ в ландшафтном режиме названия этих операций не умещались.
Запустим наше приложение на iPhone 6+ в портретном и ландшафтном режимах.
Запустим наше приложение на iPhone 6 в портретном и ландшафтном режимах.
Запустим наше приложение на iPad 2 в ландшафтном режимах.
Код для Swift 1.2 находится на Github. Полное решение для Swift 2.0 можно посмотреть на Github.
Татьяна, а Вы одна весь проект ведете?
Такого рода вопросы относятся к коммерческой тайне, которую без особых оснований раскрывать не принято.