Задание 3 CS193P 2016

47 views
Skip to first unread message

Ilya Dolgopolov

unread,
Jun 17, 2016, 11:42:32 AM6/17/16
to Swift [ru]
Привет

1. После какого урока лучше приступать к заданию 6 или 7го?
Я сделал часть после 5-го, в основном это переходы из одного view  в другое, те то, что было на конец-го 5го урока

2. Но вот я точно знаю, что рисование графика для меня будет непосильным моментом, я видел решение предыдущего года, с подобным заданием, и мало что понял в части метода drawCurveInRect.

3. вопрос про часть drawRect GraphView
В этом методе вы используете orign = orign ?? graphCenter но таким методом при ротации устройства центр оси координат находится не в центре устройства

если делать как у меня ниже, то все ок, тк выше graphCenter мы получаем путем преобразования центра superview в нашу систему координат

    override func drawRect(rect: CGRect) {

        orign = graphCenter

        axesDrawer.contentScaleFactor = contentScaleFactor

        axesDrawer.drawAxesInRect(bounds, origin: orign!, pointsPerUnit: scale)

    }


tatiana.kornilova

unread,
Jun 17, 2016, 1:50:40 PM6/17/16
to Swift [ru]
1. После 7-ой Лекции, на которой будет рассказано про делегирование
2. Конечно, сможете, но нужно понять "делегирование" и протоколы, а это - Лекция 7
3. В Задании есть пункт, что если дважды "тапнуть" в некоторой точке на экране, то центр координат должен сместиться в эту точку, для этого нужен origin, если он не задан, то начало координат располагается по середине.

пятница, 17 июня 2016 г., 18:42:32 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jun 23, 2016, 12:49:36 PM6/23/16
to Swift [ru]
Я застрял (( и не кому мне помочь (( думаю бросить 3-е задание и двигаться дальше(( напрочь забыл геометрию и алгебру
примеры предыдущего курса не помогают понять, что да как (((

жесты и NavigationController я конечно сделал, а вот график нет ((

пятница, 17 июня 2016 г., 18:42:32 UTC+3 пользователь Ilya Dolgopolov написал:
Привет
Message has been deleted

tatiana.kornilova

unread,
Jun 23, 2016, 4:37:10 PM6/23/16
to Swift [ru]

СМОТРИТЕ в моем репозитарии ваше Задание 3 с добавлениями https://github.com/BestKora/Calculator3ForIlya

1. Берете весь StackView целиком, как ниже показано, выдвигаете за экран и возвращаете на место по голубым линиям


Затем делаете установку ограничений с помощью самой правой кнопки в нижнем правом углу:


Затем поправляете из в Инспекторе Размера, чтобы были значения либо Standard Value,  либо 0. 
После этого "красные ошибки" системы Autolayout исчезают, остаются правда "желтые" предупреждения, но они не дают ошибку при старте.
Это поможет избавиться от ошибке при старте.
2. Я должна сделать небольшое замечание относительно построения графиков в Задании 3 по iOS 9. И, может быть, это моя вина, что я вас отослала к Заданию 3 предыдущего курса.
Обычно профессор не требует в Задании то, что он не показывает на Лекциях. Переведя почти до конца Лекцию 7, я обнаружила, что он в отличие от курса iOS 8 вообще не показывал, как выполняется делегирование, а отзывался предпочтительно использования замыканий вместо делегирования в Swift.
Поэтому Задание 3 iOS 9 мы будем выполнять по-другому.
Объявим в классе GraphView переменную - замыкание:

  var yForX: (( x: Double) -> Double?)? { didSet {setNeedsDisplay() } }


и будем ее использовать в методе  drawCurveInRect.

Логика этого метода очень простая и описана она в Задании 3 подсказке № 13

Не переусложните ваш drawRect. Просто делайте итерации по каждой пикселе (pixel) (не point) по всей ширине (width) вашего View, и рисуйте линию (или просто перемещайтесь, если последняя точка была “неправильной”) к следующей “правильной” точке."

Ширина нашего View - bounds.size.width в точках (points),а нам сказали итерировать по пикселям, следовательно мы должны умножить на contentScaleFactor, который содержит количество пикселей на одну точку в зависимости от разрешения дисплея вашего прибора (1- обычный 2 - Retina, 3- iPhone 6+)

Поэтому общее количество итераций (или пикселей) будет bounds.size.width*contentScaleFactor.


 var point = CGPoint()

 for i in 0...Int(bounds.size.width * contentScaleFactor){

            point.x = CGFloat(i) / contentScaleFactor


 А рисовать мы должны в точках (points), поэтому переводим полученное значение i в х-координату точки, разделив на contentScaleFactor и опять возвращаясь в пространство точек. Понятно, что чем больше разрешение дисплея прибора, тем больше мы будем делать расчетов, но графики всегда строятся в точках (points).

Теперь нам нужно получить у, имея функцию yForX:, где на входе Double и есть смещение по оси х:  origin.x и масштаб scale, поэтому в функцию yForX: пойдет такая координата х:


Double ((point.x - origin.x) / scale)

Получаем  Double координату Y с помощью функции  yForX:


 if let y = (self.yForX)?(x: Double ((point.x - origin.x) / scale)) {

               

                point.y = origin.y - CGFloat(y) * scale


и преобразуем ее в обратном порядке опять в точки (points).
Итак, у на есть точка point в области рисования  с координатами (x,y). Это точка может быть нормальной, а может быть с бесконечной координатой Y. В
зависимости от этого мы либо соединяем ее с предыдущей точкой

 path.addLineToPoint(point)


Либо просто перемещаемая в нее, не проводя линию


 path.moveToPoint(point)


Я вставила в ваш код функцию drawCurveInRect и обеспечила передачу замыкания в GraphView - посмотрите как. Больше ничего не трогала.

Но у вас проблема с расчетом program в CalculatorBrain.

Если я задаю нарисовать функцию M, то отладочная печать должна давать

х = 1 у = 1

х = 2 у = 2

и т.д.

У вас везде 0:


СМОТРИТЕ в моем репозитарии ваше Задание 3 с добавлениями 

https://github.com/BestKora/Calculator3ForIlya



четверг, 23 июня 2016 г., 19:49:36 UTC+3 пользователь Ilya Dolgopolov написал:

tatiana.kornilova

unread,
Jun 23, 2016, 5:09:14 PM6/23/16
to Swift [ru]
Ваша ошибка в том, что при изменении значений переменных в CalculatorBrain вы не обновляете program:

 var variableValues: Dictionary<String, Double> = [:] {

        didSet {

            // если мы меняем "переменные", то перезапускаем program

            program = internalProgram

        }

    }

После этого изменения Задание 3 с моими добавлениями будет работать. 
https://github.com/BestKora/Calculator3ForIlya

четверг, 23 июня 2016 г., 19:49:36 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov

unread,
Jun 24, 2016, 1:18:31 AM6/24/16
to Swift [ru]
Татьяна БОЛЬШОЕ спасибо за разъяснения, проанализирую ваши рекомендации, чтобы их понять, спасибо.

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

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

Ilya Dolgopolov

unread,
Jun 24, 2016, 1:29:29 AM6/24/16
to Swift [ru]

Еще вопрос по drawRect

//orign = graphCenter
orign
= orign ?? graphCenter

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

Поясните пожалуйста, смысл подобной конструкции?

tatiana.kornilova

unread,
Jun 24, 2016, 1:47:27 AM6/24/16
to Swift [ru]
Илья, если вы скачали мои предложения из Github, могу я их убрать из своего репозитория?

пятница, 24 июня 2016 г., 8:18:31 UTC+3 пользователь Ilya Dolgopolov написал:

tatiana.kornilova

unread,
Jun 24, 2016, 2:27:45 AM6/24/16
to Swift [ru]
origin - это Optional, пока вы его не установили, то есть nil, то считается  graphCenter
Вы его устанавливаете только когда управляете жестом tap
У вас кстати ошибка; вместо origin - orign, а в моих добавках - origin. Тяжело читать текст.
Что вас смущает? Пришлите картинки.
Посмотрите  Nil Coalescing Operator
пятница, 24 июня 2016 г., 8:29:29 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov (llodi)

unread,
Jun 24, 2016, 2:42:52 AM6/24/16
to tatiana.kornilova, Swift [ru]
Да! Большое спасибо 

---
Best regards,
Ilya

24 июня 2016 г., в 8:47, tatiana.kornilova <tatiana....@gmail.com> написал(а):

--
Вы получили это сообщение, поскольку подписаны на одну из тем в группе "Swift [ru]".
Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/rEBgaclfjfU/unsubscribe.
Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+u...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес swi...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/swiftru/be4d037a-9534-4eb9-b9c4-d444fde23fb4%40googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Ilya Dolgopolov

unread,
Jun 24, 2016, 3:01:50 AM6/24/16
to Swift [ru]
Если в drawRect origin = origin ?? graphCenter
то




если как у меня origin = graphCenter то


Auto Generated Inline Image 1
Auto Generated Inline Image 2

tatiana.kornilova

unread,
Jun 24, 2016, 8:55:58 AM6/24/16
to Swift [ru]
Да, Илья, вы правы. 
Выражение origin = origin ?? graphCenter - это ошибка. 
Мы не можем сами присваивать origin, он должен устанавливаться жестами pan и tap.
Сделаем origin вычисляемым public свойством, а устанавливать будем (не мы, а жесты) private свойство setOrigin и "ловить" его установку в вычисляемом свойстве origin 

  private var setOrigin: CGPoint? { didSet { setNeedsDisplay() } }

    

    var origin: CGPoint {

        get {

            return setOrigin ?? CGPoint(x: bounds.midX, y: bounds.midY)

        }

        set {

            setOrigin = newValue

        }

    }


Свойство origin теперь уже не Optional и все восклицательные ! знаки можно убрать.
В drawRect никакие установки origin не нужны.

    override func drawRect(rect: CGRect) {

        axesDrawer.contentScaleFactor = contentScaleFactor

        axesDrawer.drawAxesInRect(bounds, origin: origin, pointsPerUnit: scale)

        drawCurveInRect(bounds, origin: origin, pointsPerUnit: scale)

    }

Все работает с таким предложение, можно посмотреть код для Задания iOS 8 здесь.

То, что предлагаете вы:


origin = graphCenter


Не будет работать для жестов, ведь мы должны менять origin.
Все это относится к подсказке №11 Задания 3

"Было бы прекрасно, если бы origin для вашего графика по умолчанию разместился в середине UIView. Но будьте внимательны где/ когда вы рассчитываете это, потому что границы ( bounds) вашего UIView не будут установлены до тех пор, пока UIView не расположится на устройстве. Вы можете быть уверены, что границы (bounds) вашего UIView уже установлены в вашем drawRect. Но будьте внимательны, чтобы не переустановить заново origin, если он уже был кем-то установлен."

Вы - молодец. Спасибо за настойчивость.
У меня к вам просьба. Где вы еще видели у меня код origin = origin ?? graphCenter ?
В одном месте я исправила, а может быть вы скачали какой-то другой Калькулятор iOS 8 (у меня их много)?
Хочу исправить во всех остальных местах.

пятница, 24 июня 2016 г., 10:01:50 UTC+3 пользователь Ilya Dolgopolov написал:

Ilya Dolgopolov (llodi)

unread,
Jun 26, 2016, 8:22:31 AM6/26/16
to tatiana.kornilova, Swift [ru]
Татьяна, я не качал :( я просто смотрел как в описании решения и пробовал сам, хотя «сам» - очень сложно идет ((

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

Вот задание с Face или Твиттер - это классно, вообще побольше б прикладного, чего-то было, соц сети работа с интернетом + обучение swft ))

Ilya Dolgopolov (llodi)



24 июня 2016 г., в 15:55, tatiana.kornilova <tatiana....@gmail.com> написал(а):

--
Вы получили это сообщение, поскольку подписаны на одну из тем в группе "Swift [ru]".
Чтобы отменить подписку на эту тему, перейдите по ссылке https://groups.google.com/d/topic/swiftru/rEBgaclfjfU/unsubscribe.
Чтобы отменить подписку на эту группу и все ее темы, отправьте письмо на электронный адрес swiftru+u...@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес swi...@googlegroups.com.
Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке https://groups.google.com/d/msgid/swiftru/d0e329c9-0b0b-48f6-86c2-75020dbb0df3%40googlegroups.com.
Message has been deleted

Ivan Lazarev

unread,
Jul 4, 2016, 7:18:18 AM7/4/16
to Swift [ru]
удалил последний вопрос, т.к он уже задавался

пятница, 17 июня 2016 г., 18:42:32 UTC+3 пользователь Ilya Dolgopolov написал:

Ivan Lazarev

unread,
Jul 4, 2016, 10:12:54 AM7/4/16
to Swift [ru]
написал вопрос, потом удалил, а теперь решил все-таки прояснить:
пересмотрел лекцию 6, и в ней профессор явно говорит сделать задание (и завершить reading assignment) до лекции 7...так же и в things to learn к заданию 3 отсутствуют делегирование, замыкания и NSUserDefaults...может быть они упрощают выполнение задания, но профессор хочет чего-то другого?


пятница, 17 июня 2016 г., 18:42:32 UTC+3 пользователь Ilya Dolgopolov написал:
Привет

tatiana.kornilova

unread,
Jul 4, 2016, 10:41:02 AM7/4/16
to Swift [ru]
В Задании 3 есть обязательный пункт 8:
Графический View не должен владеть (то есть запоминать) данные, представляемые графически, даже временно. Он должен запрашивать данные, если это необходимо. Ваш графический view должен строить график функции y(x), он не должен графически отображать массив точек, не передавайте ему массив точек.

Как вы будете выполнять этот пункт? Есть только два способа у View запрашивать данные: делегирование и замыкания. Делегирование  в разделе things to learn из Задания 3 iOS 9 он действительно исключил, наверно, предполагая, что вы должны сделать упор на замыкание. Кстати в Лекции 7 он говорит о том, что обычно он все объясняет на лекциях и только потом дает задание, но на лекции 7 он сказал, что это не получилось с Заданием 3 и стоит рассмотреть использование замыканий в Задании 3 вместо делегирования.

Что касается NSUserDefaults, то это дополнительный пункт 2:

Сохраните origin и scale между запусками вашего приложения. Где это следует сделать, оказывая наибольшее уважение MVC, как вы думаете? Нет однозначно “правильного ответа” на этот вопрос. Это требует некоторой утонченности знания  MVC.
Не указывая  NSUserDefaults, он дает вам свободу для решения этого пункта, но я не вижу другого способа, кроме как NSUserDefaults или сохранить в файле или базе данных Core Data. Но ни Core Data, ни Persistance он еще не читал. Может быть он надеется на некоторое неординарное решение? Надо сказать, что раньше в Заданиях было больше подсказок (например iOS 8), поэтому, если задания похоже, то иногда можно заглянуть и в старое Задание;

понедельник, 4 июля 2016 г., 17:12:54 UTC+3 пользователь Ivan Lazarev написал:

Ilya Dolgopolov

unread,
Jul 4, 2016, 1:23:36 PM7/4/16
to Swift [ru]
посмотрел код и описание решения 3-го задания! Вы многое переработали и оптимизировали,

Я правильно понял смысл замыкания: это возможность определить переменную, что берет функцию в качестве аргумента в одном классе, а реализацию делать в другом классе, при этом в этой реализации возможен захват свойств и методов класса, где реализуется замыкание?

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

tatiana.kornilova

unread,
Jul 4, 2016, 2:38:17 PM7/4/16
to Swift [ru]
Звучит страшно, но, по-моему, вы правильно уловили идею. С ней надо поработать.

понедельник, 4 июля 2016 г., 20:23:36 UTC+3 пользователь Ilya Dolgopolov написал:

Ivan Lazarev

unread,
Jul 18, 2016, 9:15:05 AM7/18/16
to Swift [ru]
Всем привет!
Реализовал обязательные пункты, как мне кажется...приступаю к дополнительным, буду признателен, если кто-нибудь посмотрит мое решение :)

https://github.com/ballard/calculatorMVC-V2/tree/graphicalCalc

пятница, 17 июня 2016 г., 18:42:32 UTC+3 пользователь Ilya Dolgopolov написал:
Reply all
Reply to author
Forward
0 new messages