Задание 2. Решение — начало (обязательные пункты 1-4) Swift 1.2 и Swift 2.0

Текст Домашнего задания на английском языке доступен на  iTunes в пункте “Developing iOS 8 app: Programming: Project 2″.  Текст Домашнего задания на русском  языке доступен на 

Задание 2 iOS 8_new.pdf

Результаты выполнения задания можно обсуждать на форуме Swift[ru] . Ваше решение может быть лучше и интереснее. Выкладывайте его в Github, давайте ссылку на Dropbox или используйте другие системы управления версиями. Xcode  работает напрямую с Github.

Пункт 1 обязательный

Все изменения, сделанные с калькулятором Calculator на лекции, должны быть внесены в код вашего Задания 1. Сделайте полученный Calculator полностью функционирующим прежде, чем вы приступите к выполнению остальных обязательных заданий. И, как и в прошлый раз “печатайте” изменения в коде, а не используйте copy / paste.

В этом пункте мы должны совместить изменения в коде, сделанные на Лекции 3, когда происходит разделение на Модель и Controller, и калькулятор, который получился при выполнении Задания 1 без разделения на Модель и Controller. Это калькулятор описан в посте.

Код можно посмотреть на Github.

Пункт 2 обязательный

Ничего не меняйте в non-private API в CalculatorBrain и продолжайте использовать enum в качестве основной внутренней структуры данных.

Здесь стоит привести наш non-private API в CalculatorBrain.
У меня это:

[js]
func pushOperand(operand: Double) -> Double?
func performOperation(symbol: String) -> Double?
func evaluate() -> Double?
func displayStack() -> String?
[/js]

Пункт 3 обязательный

Ваш пользовательский интерфейс (UI) должен быть всегда синхронизирован с вашей Моделью (CalculatorBrain).

Пользовательский интерфейс, который нужно синхронизировать с Моделью, соcтоит из двух меток: метка display (дисплей нашего калькулятора) и метка history  (историей ввода операндов и операций).

Синхронизация метки display и Модели осуществляется через «вычисляемую» переменную displayValue, значение которой мы задаем на основании результатов использования функций API нашего калькулятора pushOperand и performOperation. Эти функции API  возвращают Optional значения, следовательно, переменная displayValue также должна быть Optional
Screen Shot 2015-08-22 at 10.17.04 PM
Screen Shot 2015-08-22 at 10.08.59 PM
и мы плавно переходим к пункту 4, который у нас уже выполнен в Задании 1.
Метка history устанавливается синхронно с установкой значения  displayValue в set {} 
Screen Shot 2015-03-26 at 10.42.12 AM
с использованием функции displayStack из API нашей Модели
Screen Shot 2015-03-26 at 10.49.28 AM
В дополнительном пункте 2 Задания 1 нас просили добавить в конце метки  history  знак «=», если число на дисплее показывает результат вычисления, а не только что введенное число. Мы должны это сделать при получении результатов выполнения любой операции
Screen Shot 2015-03-26 at 2.27.12 PM

Пункт 4 обязательный

Дополнительное задание с прошлой недели превратить displayValue в Double? ( то есть сделать его Optional, а не Double) теперь является обязательным. displayValue должен возвращать nil, если содержимое display не может интерпретироваться как Double. Установка displayValue  в nil должна очищать display.

После объявления displayValue как Double? мы можем в get{ } использовать цепочки Optional, а в  set{ }  — очищать display в случае установки в nil. Режим  get{} работает при передачи числа с экрана в CalculatorBrain с помощью API функции pushOperand , а режим  set{ } работает при выводе на экран результата, полученного с помощью API функции performOperation.
Screen Shot 2015-03-26 at 10.42.12 AM  Одновременно в set{ } вы должны модифицировать метку history с историей ввода операндов и операций

 history.Text = brain.displayStack ?? » «

Функция addHistory, используемая в Задании 1 большее нужна, так как полный список операндов и операций мы получаем из класса CalculatorBrain с помощью  функции displayStack из API нашей Модели.

C numberFormatter(), используемом в вычисляемой переменной displayValue, мы получим интересные результаты. Например, для стэка  [1.0, 0.0,  ÷] деления 1.0 на 0.0 результат будет устанавливаться в «бесконечность».
Screen Shot 2015-08-22 at 10.28.22 PM

А нам бы хотелось получать значение nil, чтобы очищать экран и сообщать об ошибке в строке history, поэтому внесем небольшие коррективы в код функции evaluate()  нашего API в Модели CalculatorBrain

Screen Shot 2015-08-22 at 10.34.50 PM

 

Код для Swift 1.2  и iOS 8.4 можно посмотреть на Github.

Код для Swift 2.0  и iOS 9 можно посмотреть на Github.

Наш новый калькулятор с разделенными Моделью и Controller должен работать абсолютно также, как и калькулятор в Задании 1.
Теперь мы готовы к добавлению новых функциональных возможностей к нашему калькулятору.
Продолжение следует…