Задание 1 cs193p Winter 2015 Калькулятор Swift 1.2 и Swift 2.0

Содержание

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

Задание 1 iOS 8.pdf

Начинаем выполнять Задание 1 с кода, полученного в конце Лекции 2 с учетом уточнений для Swift 1.2. Профессор настоятельно рекомендует не копировать код в первых 2-х Заданиях, а непосредственно печатать, так как это даст хороший опыт освоения среды разработки Xcode. Я все-таки привела на Github код демонстрационного примера, соответствующий окончанию Лекции 2. Это позволит совсем начинающим не «застрять» на самом первом этапе.

Ниже приводится решение всех пунктов задания для тех, кто хочет сравнить свой результат с моим, и окончательный код  Задания 1 на Github.

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

Ваш калькулятор (calculator) уже умеет работать с числами с плавающей точкой (например, если вы последовательно будете нажимать на клавиши 3 ⏎ 4 ÷  то он покажет правильный результат  0.75), тем не менее, пока нет ввода чисел с плавающей точкой. Это надо исправить. Разрешите вводить только правильные числа с плавающей точкой (напримр,  “192.168.0.1”  — неправильное число с плавающей точкой). Вам нужно добавить новую кнопку с точкой “.”. В этом задании не беспокойтесь о точности.

Прежде всего надо сделать небольшое замечание относительно точки «.» как десятичного разделителя.

Замечание. Если вы будете использовать символ  точки «.» в качестве десятичного разделителя в Задании 1, то оно может работать на симуляторе и не работать на вашем реальном устройстве, если Регион на вашем приборе установлен так, что там не применяется «.» для десятичных чисел. В этом случае приложение закончится аварийно. Но приложение должно работать в любом Регионе.

Для того, чтобы не зависеть от Региона, лучше получать разделитель для десятичных чисел непосредственно в вашем калькуляторе :

Screen Shot 2015-03-25 at 8.13.14 PM

Но вернемся к нашему пункту Задания и попытаемся заблокировать повторный ввод десятичного разделителя, который дальше по тексту мы будем условно называть «точкой», хотя, как мы уже знаем, это — не всегда точка. Для блокировки повторного ввода точки проще всего использовать функцию rangeOfString при вводе любой цифры (к которым относится и точка). Для этого нам понадобится всего одна строка

Screen Shot 2015-08-19 at 9.05.30 AM
Случай ввода в калькулятор числа “.5” работает правильно без дополнительного кода.
Если мы пойдем немного дальше, исследуя десятичный разделитель, то нам захочется иметь кнопку не с точкой «.», а с тем знаком, который принят в этом Регионе. Для этого сделаем outlet для кнопки с условным названием «точка»

Screen Shot 2015-03-25 at 8.21.37 PM

Screen Shot 2015-03-24 at 8.45.26 PM
Мы должны установить заголовок этой кнопки равным decimalSeparator и это можно сделать двумя способами :

  1. с использованием метода viewDidLoad () «жизненного цикла» Controller (об этом будет лекция 8); этот метод срабатывает один раз при загрузке Controller
  2. с использованием Наблюдателя didSet{} Свойста @IBOutlet weak var tochka; этот метод вызывается один раз при  установке этого outlet  со  storyboard

Первый способ связан с добавлением метода viewDidLoad ()

Screen Shot 2015-03-24 at 11.32.10 PM

Второй метод использует Наблюдателя Свойства tochka didSet {}

Screen Shot 2015-03-24 at 11.37.09 PM

Я выбрала второй метод и для проверки поставила на кнопке не «.«, а три символа «Poi«, которые должны заменится на десятичный разделитель decimalSeparator, взятый из NSNumberFormatter()

Screen Shot 2015-03-25 at 7.17.51 AM

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

Добавьте следующие 4 кнопки с операциями:

  • sin : вычисляет sin операнда на вершине стэка.

  • cos : вычисляет cos операнда на вершине стэка.

  • sqrt : вычисляет √ (квадратный корень) операнда на вершине стэка.

  • π: вычисляет (ассоциируется) с величиной π. Например: 3 π × должно показать на дисплее (display) вашего калькулятора величину π, умноженную на 3, точно также  3  π ×,  и  π 3 × должны показывать величину π, умноженную на 3.

Добавляем заголовки к безымянным кнопкам справа и проверяем, что все ли они подсоединены к Action @IBAction func operate(sender: UIButton)  
Screen Shot 2015-08-16 at 11.12.08 AM
Добавляем еще одну функцию performOperation для операции, соответствующей  возвращению константы (входные операнды не нужны)
Screen Shot 2016-03-10 at 4.33.54 PM
Первая функция для констант — у нее в параметре operation нет входных операндов. Вторая функция для унарный операций — у нее в параметре operation один входной операнд. Третья функция для бинарных операций — у нее в параметре operation два входных операнда.
Хочу обратить ваше внимание на наличие у всех функций атрибута @nonobjc. Пока не обращайте на это внимание, но если вам очень любопытно, то посмотрите пост «Дополнение к Лекции 2 — особенности кода Calculator в Swift 1.2 и Swift 2.0 или как не «застрять» на этом месте.»
Добавляем указанные в этом пункте 4 функции: sin, cos, sqrtπ.

Screen Shot 2015-08-16 at 8.14.27 PM
Кроме этого добавим операцию ± замены знака числу, когда оно полностью введено, что составляет часть дополнительного пункта 3 Задания 1.

Теперь объясним, почему при вызове функций performOperation входный параметр оформлен как замыкание без круглых скобок. Дело в том, что если последним входным параметром для функции является замыкание, то его можно вынести за круглые скобки. Для функций performOperation это единственный входной параметр, поэтому скобки исчезают. Такой способ оформления вызова функций в Swift называется trailing closure (хвостовое замыкание), и как увидим дальше, используется повсеместно.

Для функций sincossqrt из стандартной библиотеки известен тип входных параметров (Double) и тип возвращаемого значения (Double), что полностью совпадает с нашими требованиями, поэтому для этих функций можно не использовать замыкание, а оставить название функции в круглых скобках. Отметим, что функции sin и cos в качестве входного параметра используют угол, представленный в радианах.

Screen Shot 2015-08-16 at 10.16.54 PM

Запускаем калькулятор и проверяем  предложенные в этом пункте комбинации
3 π ×  
3 ↲ π x   
π 3  x

Screen Shot 2015-08-17 at 8.31.37 PM

Код этого пункта задания на Github.

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

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

Добавьте UILabel на верхнюю часть  storyboard, сразу чуть ниже метки дисплея и выравняйте ее по голубым направляющим линиям слева и сверху. Задайте хвостовой, лидирующий зазоры и вертикальный зазор между метками. Кнопки нужно разместить заново: либо с помощью методики «сетки» или просто в верхний левый угол.

Создаем outlet для новой метки с именем history

@IBOutlet weak var history: UILabel!

Screen Shot 2015-08-16 at 10.29.26 PM

 Добавляем метод addHistory для накопления ввода операндов и операций в тексте метки history:

Screen Shot 2015-08-17 at 5.26.20 PM

Этот метод написан с учетом дополнительного пункта 2 этого Задания, в котором предполагается добавлять знак равенства «=» при нажатии пользователем на любой клавише с операциями. Поэтому предполагаем, что знак «=» может находится в тексте метки от предыдущей операции, и убираем его, чтобы избежать повторного употребления.
Метка history формируется при вводе операнда:
Screen Shot 2016-03-10 at 4.51.59 PM
и операции:
Screen Shot 2015-08-17 at 5.40.40 PM
Запускаем. Получаем требуемый результат.
Screen Shot 2015-08-17 at 8.42.36 PM
Замечание. Установленная таким образом метка history при отсутствии в ней информации сжимается, и цифровая клавиатура калькулятора немного поднимается вверх, а при появлении информации в метке history цифровая клавиатура калькулятора немного поднимается вниз. Это не очень хорошо. Нужно поместить пробел » » ( именно » «, а не «») в метку на  storyboard.
Screen Shot 2015-08-17 at 8.46.01 PM
Усекаем головную часть строки history, чтобы видеть последние элементы ввода опрандов и операторов.
Есть еще один момент — лидирующие нули. Сейчас возможен ввод чисел с лидирующими нулями (например, “000” или “0367”).
Я предлагаю для уничтожения лидирующих нулей следующий код
Screen Shot 2015-02-11 at 7.23.41 PM

Код этого пункта задания на Github.

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

Добавьте кнопку “C”,  которая будет чистить все  (ваш дисплей ввода, новую метку, которую вы только что добавили). При нажатии кнопки “C”. калькулятор должен находится в таком же состоянии как при старте.

Добавляю снизу еще ряд кнопок и одной из них даю название «С». Создаем Action clearAll. Внутри метода помещаем код и не забываем очистить метку history, но не пустой строкой «», а пробелом » «.
Screen Shot 2015-08-19 at 10.24.40 AM

Код этого пункта задания на Github.

Пункт 1 дополнительный (extra credit)

Дайте возможность пользователю нажимать кнопку  “backspace” если он ввел неверную цифру. Это вовсе не кнопка “undo,” так что если пользователь нажал неверную кнопку с операцией , то его ждет неудача! Вам решать как вы будете разруливать случай, когда пользователь кнопкой “backspace” полностью удалил число и все еще находится в процессе ввода числа , но оставлять дисплей (display) абсолютно пустым было бы не очень дружелюбно.                                             

Одной из добавленных снизу кнопок даю название «back«. Создаем Action backSpace
Screen Shot 2015-08-19 at 2.13.51 PM
Внутри метода помещаем код

Screen Shot 2015-08-19 at 2.18.22 PM

Этот метод работает только если пользователь находится в процессе набора числа.

Код этого пункта задания на Github.

Пункт 2 дополнительный (extra credit)

Когда пользователь нажимает кнопку операции (operation button), разместите знак pавно = в конце текстовой метки UILabel, которая добавляется в Обязательном задании ( #4). Таким образом пользователь сможет понять, является ли число на дисплее калькулятора результатом вычислений или это число только что ввел пользователь. Не позволяйте знаку “=” многократно появляться в конце метки UILabel.

Этот пункт выполнен в обязательном пункте 4. Мы добавили знак «=» при нажатии кнопки с операцией
Screen Shot 2015-08-17 at 5.40.40 PM
И предотвратили многократное его появление в методе addHistory
Screen Shot 2015-08-17 at 5.26.20 PM
В результате пользователь сможет понять, является ли число на дисплее калькулятора результатом вычислений или это число только что ввел пользователь.
Screen Shot 2015-02-12 at 1.50.41 PM

Код этого пункта задания на Github.

Пункт 3 дополнительный (extra credit)

 Добавьте +/- операцию, которая меняет знак числа на дисплее (in the display). Будьте более внимательны с этим. Если пользователь находится в середине ввода числа, вы возможно, захотите изменить знак этого числа и позволить ему продолжать его ввод, не прибегайте к “принудительному” “enter” как в других операциях. Но если вы не находитесь в середине ввода числа, то это будет работать просто как любая другая унарная операция ( например, sqrt).

Одной из добавленных снизу кнопок даю название «±«. Создаем Action  plusMinus
Screen Shot 2015-08-18 at 11.27.00 AM
Внутри метода помещаем код
Screen Shot 2015-08-18 at 11.29.41 AM
Код довольно простой: если вы находитесь в процессе ввода числа (userIsInTheMiddleOfTypingANumber ), то вы меняете знак. Если нет, то пересылаете вашу кнопку методу operate. Но для того, чтобы  «±» работала как операция, необходимо добавить ее в операции.
Screen Shot 2015-08-18 at 11.31.35 AM

Код этого пункта задания на Github.

 Пункт 4 дополнительный (extra credit)

Измените вычисляемую переменную экземпляра класса displayValue так, чтобы она была Optional Double, a не Double. Его значение должно быть nil если содержимое display.text не может быть интерпретировано как Double (вам нужно использовать документацию для понимания кода NSNumberFormatter ). Установка этого значения в nil должна очищать display.

Делаем  displayValue так, чтобы она была Optional Double — Double?, a не Double.
Начнем с get {  }
Screen Shot 2015-02-12 at 4.47.43 PM
Замечаем, что текст нашего дисплея тоже Optional, но  String — String?, поэтому вначале «развертываем» display.text и получаем displayText, который имеет тип String. Затем подаем displayText как входной параметр на вход NSNumberFormatter .
Screen Shot 2015-02-12 at 5.11.59 PM
«Pазвертываем» результат преобразования  NSNumberFormatter и получаем displayNumber, который имеет тип NSNumber
Делаем его Double и возвращаем.
Screen Shot 2015-02-12 at 5.19.17 PM
Примечание. Результат преобразования  NSNumberFormatter можно не разворачивать, а использовать так называемую chaining Optionals (цепочку Optionals), это будет в Задании 2. 
Screen Shot 2015-02-13 at 7.34.59 AM
Перейдем к set {  }. Код достаточно простой и понятный: если newValue  не равно nil,  то используем String interpolation (интерполяцию строк) для преобразования числа в строковое значение, в противном случае — очищаем дисплей.
Screen Shot 2015-08-19 at 10.40.21 AM

Замечание 1. Но здесь возникает та же проблема, что и с меткой history, при отсутствии в ней информации она сжимается до нулевых размеров, и появляется, если в ней что-то есть. Нужно поместить пробел » « ( именно » «, а не «») на наш дисплей. Поэтому внесем изменения в код установки displayValue = » «.

Замечание 2. Оставить просто пустым дисплей все-таки не очень дружелюбно, хотя именно в этом и состоит последний дополнительный пункт Задания, поэтому в метке history  с помощью добавления » Errror» мы укажем, что в этом случае возникла ошибка.
Теперь во всем коде ViewController вместо displayValue 0 ставим
displayValue = nil, кроме метода clearAll

 

Screen Shot 2016-03-10 at 5.00.37 PM

Мы присваиваем значение nil вычисляемой переменной displayValue в случае, если у операции нет необходимого числа операндов, если сама операция возвращает значение, которое невозможно преобразовать в Double или если осуществлен ввод текста, который нельзя преобразовать в Double.
Теперь мы можем запускать калькулятор со значением «0» на дисплее, а в случае ошибки экран будет пустым, но появится сообщение об ошибке в строке, отображающей историю ввода операндов и операций.

Screen Shot 2015-08-19 at 3.14.19 PM

 

Замечание 3. Один из пользователей сайта прислал такой комментарий :»при вычитании 8.2 минус 8.5 результат получается -0.300000000001.
Почему возникает этот случай? при этом 5.2-5.3 результат ровно -0.3. я не очень понимаю…»

Ответ. Действительно так, любопытно. Это связано с точностью бинарного представления числа с плавающей точкой. Если вы включите отладчик, то увидите, что число 8.2 представлено как 8.1999999999999993, а 8.5 как 8.5, так что разница будет -0.30000000000000071. Но в Double 15 десятичных значащих цифр. При вычитании близких чисел (8.2 и 8.5) точность представления разности  чисел снижается (может быть до 12 -13 значащих цифр), а нам показывается представление 15 десятичными значащими цифрами, так что цифры 71 находятся за пределами точности числа Double, но именно они и дают нам в конце 1. Кстати, число 5.2 представляется как 5.2000000000000002, а а 5.5 как 5.5, так что разница будет -0.29999999999999982, но в этом случае округление выдаст правильный результат (нам просто повезло). Для преобразования числа (8.2 -8.5) в строку мы используем String interpolation «\(newValue)», которая пытается представить все 15 десятичных цифр после точки, что неверно, так как исходное число содержало только 15 верных значащих цифр 8.20000000000000. К сожалению, мы не можем управлять форматом вывода в String interpolation, но можем получить более гибкий результат с помощью NSNumberFormatter.

Screen Shot 2015-08-19 at 3.41.43 PMМы можем использовать NSNumberFormatter со специальными свойствами при выводе результатов на displayВ NSNumberFormatter можно настраивать максимальное количество цифр после точки ( maximumFractionDigits ).В случае больших чисел нам нужны разделители групп цифр (groupingSeparator), если после точки выводится очень много знаков, то мы бы хотели ограничиться 10 знаками после точки, некоторые функции, например, √ могут возвращать значение Nan при отрицательном аргументе и нам надо указать, что это ошибка Error (notANumberSymbol). Мы получаем NSNumberFormatter со специальными свойствами при помощи функции numberFormatter()

Замечание 3. Необходимо скорректировать функцию addHistory, так как помимо знака «=» мы еще добавили строку «Error» . Необходимо уметь убирать их перед вводом нового значения, предполагая, что они не обязательно могут находится в конце строки

Screen Shot 2015-08-19 at 5.14.33 PM

 

Код этого пункта задания на Github.

————————————————————

Задание 1 для iOS 9  и Swift 2.0

Автоматически преобразуем код Swift 1.2 в Swift 2.0 с помощью меню Edit -> Convert -> To Latest Swift Syntax
Преобразования коснулись только работы со строками
Swift 1.2
Screen Shot 2015-08-19 at 6.53.23 PM
Swift 2.0
Screen Shot 2015-08-19 at 6.56.38 PM
Код для Swift 2.0 находится на Github.
На русском языке вы можете скачать здесь:

Задание 1 iOS 8.pdf

Результаты выполнения заданий можно посылать на форум Swift[ru] для обсуждения. Просьба давать развернутую оценку присланным результатам и сравнивать решения.

Задание 1 cs193p Winter 2015 Калькулятор Swift 1.2 и Swift 2.0: 23 комментария

  1. Возникает ошибка: после того как нажать enter, когда на дисплее Error. Мой вариант решения добавить switch в get переменной displayValue:
    {
    switch display.text! {
    case «Error»: display.text! = «0»
    default: break
    }
    Есть-ли еще решения?

    PS: Большое спасибо за материал

    • У меня нет Error на дисплее. В случае ошибки — дисплей пустой, как и было сказано в Задании. У меня Error только в строке, где сохраняется история ввода операций и операндов. Если у вас не так, то пришлите ваш код на Github или Dropbox. Но мыслите вы в правильном направлении. Это Задание 1 и здесь не требуется выводить текст на дисплей, но в Задании 2 вам нужно будет показать на дисплее либо числовой результат, либо ошибку — и не просто Error, а «расшифрованную» ошибку типа «Деление на ноль» или «Квадратный корень из отрицательного числа» — и в этом случае можно использовать для результат enum (перечисление) в виде
      enum Result {
      case Value(Double)
      case Error(String)
      }
      Такой тип данных при выводе на консоль использует switch
      var description: String {
      switch self {
      case .Value(let value):
      return NumberFormatter.formatter.stringFromNumber(value) ?? «»
      case .Error(let errorMessage):
      return errorMessage
      }
      }
      Однако, это одно из решений. Для Swift 2 хотелось бы увидеть решение с новыми конструкциями ErrorType, try, catch, do и throw.

  2. Привет! Нашел такую ошибку. Когда результат равен 0, он автоматически конвертируется в 0.0 на экране и тогда проверка на разделитель не работает так как точка от Double видимо не считается и можно вводить 0.0.0000. Интересно как эту ошибку пофиксить)
    принскрин http://s010.radikal.ru/i313/1512/3d/1450d5fe64d8.png

    • У меня все работает, такой ситуации, как у вас, — нет. Посмотрите мой код для Задания 2 и Задания 3 на Github. Пришлите ссылку на ваш код в Github или Dropbox — разберемся.
      Вообще-то за точку (разделитель) у меня отвечает код
      @IBOutlet weak var tochka: UIButton! {
      didSet {
      tochka.setTitle(decimalSeparator, forState: UIControlState.Normal)
      }
      }

      let decimalSeparator = NSNumberFormatter().decimalSeparator ?? "."
      . . . . . . . . . . . . . . . .
      @IBAction func appendDigit(sender: UIButton) {
      let digit = sender.currentTitle!
      if userIsInTheMiddleOfTypingANumber {

      //----- Не пускаем избыточную точку ---------------
      if (digit == decimalSeparator) && (display.text?.rangeOfString(decimalSeparator) != nil) { return }
      //----- Уничтожаем лидирующие нули -----------------
      if (digit == "0") && ((display.text == "0") || (display.text == "-0")){ return }
      if (digit != decimalSeparator) && ((display.text == "0") || (display.text == "-0"))
      { display.text = digit ; return }
      //--------------------------------------------------

      display.text = display.text! + digit
      } else {
      display.text = digit
      userIsInTheMiddleOfTypingANumber = true
      }
      }

      Я думаю все дело в вашем коде.

      • Вы были правы, дело в моем коде я добавлял еще проверку( хотел избавиться от возможности ввода .5). Понял что пусть с .5 работает 😉

  3. Добрый день! Нашел баг: Если ввести число, нажать Enter несколько раз то, в operandStack числа, разумеется, добавляются, а в History отображается, только первый ввод.

    • Да, действительно это баг. Изначально на Enter возлагалось только окончание ввода числа, потом добавилась запись в стэк, а потом еще и history. Так что я выделила запись в стэк в отдельную функцию и все упростилось
      func addStack(){
      if let value = displayValue {
      operandStack.append(value)

      }else {
      displayValue = nil
      }
      print("operandStack = \(operandStack)")
      }

      @IBAction func enter() {
      userIsInTheMiddleOfTypingANumber = false
      addHistory(display.text!)
      addStack()
      }

      В операциях вместо enter() используем addStack()
      @nonobjc func performOperation (operation: () -> Double ){
      displayValue = operation ()
      addStack()
      }
      . . . . . . . . .

      Новый код на Github.

  4. Добавлять пробелы в history, чтоб не менялась высота — это костыль какой-то.
    Есть же специально для этого height constraint.

    • Вы не первый делаете это замечание. Но если подумать, то height constraint скорее всего приведет вас к какому-нибудь конкретному числу, что с точки зрения профессора очень нежелательно, ибо будет связано с геометрическими размерами — он очень не рекомендует использовать «магические» числа в Autolayout. Так что я осознанно предлагаю идти от содержания текста, а не от геометрических размеров. Если у вас есть решение помимо конкретного числа в качестве height constraint, то с удовольствием его использую.

      • Вот оно что. Не добрался ещё до подробной лекции про Autolayout, видимо там упоминается. Действительно, замечание справедливое.
        Навскидку придумался другой полукостыль. Мне он не очень нравится. Но есть ряд преимуществ. К тому же в документации apple похожий приём (dummy views) используется.

        Решение: в interface builder добавляем рядом с historyLabel ещё один UILabel (dummyLabel) c тем же размером шрифта (и другими параметрами) и с пробелом внутри. Выставляем обоим Equal Height Constraint. Теперь «опорный пробел» из кода вынесен в storyboard.

        Но может как-то более прямо можно запретить пустой UILabel уменьшаться…

        • Такие элементы UI как метка UILabel и кнопка UIButton имеют так называемый intrinsic content size, то есть внутренний размер, определяемый текущем содержанием этих UI. Система Autolayout использует именно этот intrinsic content size для определения ширины и высоты метки или кнопки. Поэтому обычно никаких явных ограничений на высоту и ширину метки не устанавливается, а используются приоритеты Compression-Resistance (сопротивление сжатию) and Content-Hugging (способность расширяться и использовать дополнительное пространство) для регулирования взаимного положения, например, двух меток или метки и текстового поля. Поэтому надо дать системе Autolayout то, что она ждет — содержимое метки.
          Что касается dummy views, то это к меткам и им подобным не относится, у UIviews нет intrinsic content size и с ними можно проделывать всякие трюки с ограничениями.

          • Так я про dummyLabel, а не UIView. Проверил — работает.
            dummyLabel — копия historyLabel. Ширину можно сделать любую, фон прозрачный, чтоб не экране не мешала. А вот высота как раз через intrinsic будет считаться.
            Известно, что в historyLabel одна строка и что высота не должна меняться (иначе кнопки прыгают). Так что расширения и сжатия тоже не нужны.
            Поэтому текст внутри dummyLabel — пробел. Так historyLabel (даже без текста) рассчитает свою высоту с помощью equal height constraint, привязанного к dummyLabel.
            Всё это позволит избавиться от нескольких установок пробелов в коде.

            Другое дело, что код с пробелом гораздо проще и понятнее (особенно если учесть, что это первое задание). Если оставлять этот код, я б вынес назначение пробела в функцию emptyHistoryLabel, чтоб только в ней был «костыль» c объяснением, а не в нескольких местах.

          • Зачем вам dummyLabel? У вас есть display, который не бывает пустым. Возьмите от его высоты нужную долю.

          • Ааа, так тут же пробелы в разные метки ставятся! И в history, и в display. (у меня код чуть другой, display пустой не бывает)
            Тогда похоже ничего лучше и не придумаешь. Две dummyLabel делать — как-то уже слишком. Проще поддерживать высоту метки избегая пустого текста. Может в iOS9 что-нибудь добавили более прямое…

          • А что Вы помещаете в history при старте? Как посмотреть ваш код? Всегда интересны оригинальные решения.В iOS 9 есть stackView — очень хорошая вещь, но, по-моему, он нам не поможет.

          • Появилась статья «Goodbye Spacer Views Hello Layout Guides» — «Прощайте специальные Views для пробелов — Здравствуйте Layout Guides». Но, к сожалению, это только в коде, а не на storyboard ?. Apple добавила UILayoutGuide class в iOS 9 для выполнения той же самой работы, что делают dummy views без «накладных расходов», связанных с реальной «памятью» для views и их участием в иерархии views.

  5. Не понятно почему в третьей лекции на калькуляторе не видно кнопок которые нужно сделать в Задании 1

    • Обычно лекции не связаны сильно с Заданиями. Лектор никогда не выполняет за студентов Задания, он дает вам только «наброски» основных возможных решений отдельных пунктов Задания, чтобы вы самостоятельно смогли сделать задание.

  6. Во втором пункте добавил точку. Точка это обычная точка или какой-то особый знак из набора XCode ? При запуске при нажатии на кнопку с точкой она не появляется на экране и число не разделяет. В чем может быть проблема?

  7. Добавил кнопку с точкой, но во время работы при нажатии на кнопку точка не появляется на экране и не разделяет число. В чем может быть проблема?

    • Если вы работаете на Симуляторе, то проблем не должно быть. Если вы работаете на реальном приборе, то возникают проблемы, связанные с регионом, где вы находитесь. Используется ли точка там в качестве десятичного разделителя? Эту проблему решали здесь много раз и на форуме, и в посте Задание 1 cs193p Winter 2015 Калькулятор Swift 1.2 и Swift 2.0

  8. У меня на Main.storyboard не влазят остальные кнопки, как можно их добавить? Уменьшить размер всех кнопок?

Обсуждение закрыто.