Лекция 1 CS193P Winter 2015 — Логистика курса, обзор iOS 8. (часть 2)

Title iOS 8

STANFORD UNIVERSITY:

Разработка iOS 8 приложений с Swift CS193P

 Лекция 1: Логистика курса, обзор iOS 8

Профессор Пол Хэгарти (Paul Hegarty)

Начало: 1 — ая часть лекции (0 — 35 минут) можно найти здесь.

Продолжение: 2 -я часть лекции (35 минута  — конец).

Давайте немного поговорим о связи пользовательского интерфейса, который мы только что создали, с нашим кодом. Мы хотим, чтобы код имел возможность «разговаривать» с пользовательским интерфейсом. Иначе как мы заставим цифры на кнопках, которые мы нажимаем при наборе числа»,  появиться на нашем дисплее, или как нам получить результат умножения, если мы нажали кнопку с заголовком «x»? Нам нужно научиться разговаривать с нашем интерфейсом.

Как мы будем это делать? Во-первых, нам нужно, чтобы и код ( файл ViewController.swift ), и интерфейс (файл Main.storyboard) появились на экране в Xcode одновременно, так как мы собираемся их связывать.

Есть много способов сделать это, но наиболее простой заключается в маленькой кнопке в верхней правой части Xcode, вызывающей Assistant Editor (Ассистента Редактора). Если я на ней кликну, то мы получим оба файла на экране,то есть то, что я хотел.

Screen Shot 2015-01-29 at 5.31.40 PM
Но на этом экране слишком много всего. Прежде всего я хотел бы расширить пространство для моего кода. К счастью, мы можем скрыть Навигатор (слева) и Область Утилит (справа)

Screen Shot 2015-01-29 at 5.39.59 PMТеперь у меня на экране как интерфейс, так и код.

Screen Shot 2015-01-30 at 7.02.08 PM

Я, конечно, мог бы дважды кликнуть на UI с тем, чтобы уменьшить экран ( zoom out ), но дело в том, что все привязки UI к коду можно осуществлять только в нормальном масштабе.  Если я попробую сделать CTRL- связывание в уменьшенном масштабе интерфейса, то у меня не получится. Уменьшенный масштаб ( zoom out ) применяется как «взгляд с птичьего полета» для обзора всего пользовательского интерфейса, а если вы хотите реально работать с интересующем вас scene (эпизодом) , то вам нужно дважды кликнуть на нем ( zoom in ) и вывести его  в нормальный режим просмотра. Справа в Xcode у меня Swift код. Я удалю внутреннюю часть целиком, так как это мне не нужно для калькулятора. Это наш первый взгляд на Swift.

Как я уже говорил Swift — очень краткий язык, объектно-ориентированный, он выглядит очень похоже на C, некоторые вещи выглядят также как в Java. Он вобрал в себя лучшее из различных языков.
Предложение

[js]
import UIKit
[/js]

позволяет импортировать часть iOS, связанную с UI. Обычно вам не нужно ничего импортировать специального до тех пор, пока вы не начнете использовать
frameworks, которые не являются базовыми. Возможно через несколько недель нам придется что-то импортировать самостоятельно, но в данном случае за нас все сделали автоматически.
И это ваш первый код на Swift. Это определение класса, потому что фундаментально Swift — объектно-ориентированный язык.

Screen Shot 2015-01-29 at 5.54.04 PM

Что собой представляет синтаксис?
У нас есть ключевое слово class, затем следует имя класса,  ViewController (кстати, очень плохое имя, так как оно слишком обобщенное), нужно что-то типа CalculatorViewController, отражающее специфику того scene, над которым мы работаем и которое управляется этим кодом. А имя ViewController  задается по умолчанию. Я не хочу тратить время на переименование этого класса.
Для первого домашнего задания можно оставить и ViewController, но дальше вам следует подбирать более подходящее имя. И, конечно, вы будете создавать множество scenes на этом курсе и в будущих приложениях и они должны иметь разные имена.  Но пока на этом курсе класс ViewController, который наследует от класса  UIViewController. Класс UIViewController является superclass для ViewController. Swift — это язык с одиночным наследованием, так что наследовать можно только от одного класса. Для Swift можно вообще не наследовать ни от какого класса. Но в нашем случае мы наследуем от UIViewController, потому что нам нужна вся эта фантастическая функциональность, которая позволяет управлять UI, например, такая как Autolayout (Разметка), и многие другие. Поэтому все эти маленькие контроллеры,  scenes, всегда наследуют от UIViewController напрямую или от класса, который наследует от UIViewController  или от любого в этой цепочке.

В фигурных скобках задаются переменные  экземпляра класса (instance variables) и методы. Очень простой синтаксис при определении класса. Давайте попробуем создать несколько переменных экземпляра класса и методов.
Но прежде подсоединим нашу метку для дисплея к коду и создадим переменную экземпляра класса.
Переменные экземпляра класса в  Swift называются property (свойства), поэтому если вы слышите, что я говорю  property, то я имею ввиду переменную экземпляра класса. Такие переменные — это часть класса, и каждый экземпляр класса имеет свои собственные копии этих переменных. Я собираюсь создать property, переменную экземпляра класса, которая указывает на нашу метку, так что я смогу изменять текст метки. Я хочу «разговаривать » с меткой. Сделать подсоединение метки к коду можно в Xcode путем CTRL — перетаскивания, как мы делали это при разметке положения метки на экране, но вместо «перетаскивания» к краю контейнера, мы перетащим ее прямо в код. После того, как вы отпустим мышку, всплывет окно, в котором вы должны дать имя нашей outlet связи.

Screen Shot 2015-01-29 at 7.06.04 PM

outlet означает переменная экземпляра класса (instance variable) или свойство (property), которое указывает на эту вещь в пользовательском интерфейсе. Все что вас спрашивает всплывшее окно — это имя этой outlet связи или свойства (property).

Мы назовем это свойство display и оно уже знает свой тип — это UILabel, потому что мы тянули нашу связь от этой метки. Не беспокойтесь о Weak, я расскажу об этом через секунду. Нажимаем на Connect, и создается свойство прямо в нашем Контроллере.

Screen Shot 2015-01-29 at 7.35.24 PM

У нас появилась прекрасная возможность посмотреть на синтаксис  Swift для созданного свойства (property). Но есть пара вещей, которые не являются собственно синтаксисом Swift. Часть

[js]
var display: UILable!
[/js]

является обычной частью при декларации свойства в Swift.
Часть

[js]
@IBOutlet weak
[/js]

в действительности не является частью синтаксиса Swift, это то, что Xcode размещает здесь и еще есть маленький кружочек, на который я могу навести мышкой и Xcode покажет  на UI к чему подсоединена эта строка кода.

Screen Shot 2015-01-29 at 7.50.01 PMЭто очень здорово и в Демо мы увидим как это работает при поиске того, что подсоединено к нужной строке кода. @IBOutlet не нужно печатать самому, это появляется при CTRL- связывании.

Теперь, что касается weak. Те из вас, кто пришел из других языков, привыкли к таким понятиям как garbage collection (сбор мусора), используемым при очистке «кучи» (heap). Или возможно, вы делали размещение ( alloc ) и освобождение (free) некоторых объектов вручную в других языках. Ничего подобного нет в Swift. В Swift все объекты «живут» в «куче» ( heap). Все классы, все экземпляры классов «живут» в «куче» ( heap). И вместо вас управление памятью для них происходит автоматически. Вы размечаете их столько, сколько хотите, но как только вы на них не указываете, они удаляются из «кучи, и никакого garbage collection (сбора мусора). Здесь работает механизм подсчета ссылок ( reference counting). Этот механизм действительно считает ссылки на эти объекты, но происходит это все автоматически. Единственное, что вас может заинтересовать  в этом механизме — это работа с weak, но вам придется иметь с этим дело в меньше чем 0.01 % случаев. В первые 4 недели на этом курсе о weak можно забыть. Этот weak создается автоматически при  CTRL-  связывании и вы можете игнорировать его.
Главное, что вы должны знать — это то, что управление памятью происходит автоматически, без вашего участия.
Хочу также заметить, что переменная экземпляра класса display, которая является указателем на объект, не содержит никаких  амперсандов & и звездочек * или какого-то другого синтаксиса, который давал бы понять, что это указатель.

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

Но вы видите восклицательный знак, ! , между прочим, и я поговорю об этом через несколько минут. Но он  не имеет никакого отношения к объектам.  Это абсолютно другое и мы доберемся до этого.

Давайте еще раз взглянем на определение свойства (property) или переменной экземпляра класса

[js]
var display: UILable!
[/js]

var — это сокращение для variable (переменная), потому что это действительно переменная.

display —  имя переменной,

:UILabell! — это тип переменной экземпляра класса.

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

Теперь поговорим о связи другого типа. Давайте начнем размешать кнопки на нашем калькуляторе. Я вернусь в Область Утилит и из Библиотеки объектов достану кнопку  UIButton и перетяну ее на мой Controller. Я не буду выравнивать кнопку по голубым линиям прямо сейчас, я сделаю это позже. Пусть эта кнопка будет левой верхней кнопкой нашей цифровой клавиатуры, то есть цифрой 7.

Screen Shot 2015-01-29 at 9.53.32 PMЯ меняю размер шрифта с 17 на 24 в Инспекторе Атрибутов. меняю размер кнопки на 64 x 64. Последнее можно сделать непосредственно на экране с помощью маленьких квадратиков, а можно сделать в Инспекторе Размера (Size Inspector)

Screen Shot 2015-01-29 at 9.57.17 PMИтак, у нас есть цифра 7. Если я нажму цифру 7, что я хочу, чтобы произошло?
Эти цифры должны появляться на нашем дисплее. Вот что должен делать наш Controller.
Когда мы касаемся этой кнопки, мы хотим, чтобы она послала сообщение нашему Controller. Надеюсь, вы знаете, что сообщение — это метод для моего класса. Для того, чтобы это стало возможным, мы сделаем тоже самое, что и в прошлый раз: CTRL — перетягивание от кнопки в наш код. Но в появившемся всплывающем окне мы выберем не  Outlet   связывание, потому что в данном случае мне нужна не переменная экземпляра класса, а метод. Мне нужна функция в моем классе, и я хочу, чтобы она  послала сообщение нашему Controller. Поэтому вместо Outlet,  я выбираю Action:

Screen Shot 2015-01-30 at 9.05.21 AM

Action — это немного другое, чем OutletOutlet означает создание переменной экземпляра класса, Action означает создание метода. В всплывающем окне необходимо указать имя метода. Исходим из того, что нажатие на эту кнопки будет делать. Я хочу, чтобы при нажатии на эту кнопку, цифра, указанная в заголовке, добавлялась к нашему дисплею, поэтому я называю метод  appendDigit. Это будет один и тот же метод для всех цифр, и, следовательно, для всех кнопок. Но в этом едином метода я должен знать, какая кнопка послала мне сообщение. К счастью, при посылке сообщения в качестве аргумента метода Arguments указывается отправитель — sender. Но можно и не указывать аргументы и установить значение Arguments в None. Единственная запутанная вещь здесь, я не знаю зачем они это сделали в  Xcode, надеюсь в будущих версиях они это исправят, — это то, что тип объекта, посылающего Action, по умолчанию выставляется AnyObject. Мы поговорим об AnyObject на следующей неделе, но нам не нужен AnyObject сейчас, так как я точно знаю, что sender — это UIButton и переключаю с помощью маленькой синенькой штучки на UIButton. Если вы забудете сделать это переключение в вашей домашней работе, то это приведет к затруднениям. Не забудьте это сделать. Event (событие), которое посылает сообщение — это Touch Up Inside (касание кнопки в середине и поднятие пальца вверх) просто означает нажатие кнопки. В результате получим следующий результат.

Screen Shot 2015-01-30 at 9.09.24 AM

Если я нажимаю на Connect,  я получаю метод с одним аргументом, которым является sender с типом which is a UIButton. Это мой первый метод в Swift.
Screen Shot 2015-01-30 at 9.16.23 AMИ опять вы видите здесь @IBAction похожую на@IBOutlet. Они порождают такие обведенные точки слева, с помощью которых можно видеть к чему они подсоединены в UI. А дальше — нормальный Swift синтаксис метода, который начинается с func , потому что это функция, метод — это функция, определенная в классе. Затем имя appendDigit, затем в круглых скобках аргументы, перечисленные через запятую. У нас один аргумент. У него указывается имя —sender, это имя для использования внутри нашего метода — и тип UIButton. И заметим, что нет восклицательного знака !. Если метод, что-то возвращает, а наш метод ничего не возвращает, то он будет выглядеть иметь стрелочку с указанием типа возвращаемого значения.

Screen Shot 2015-01-30 at 9.32.00 AM

Но у нас нет возвращаемого значения, поэтому уберем его вообще.

Как видите, очень простой синтаксис.

Прежде чем пойти дальше, сделаем все кнопки нашей цифровой клавиатуры. Будем использовать copy / paste, но следите за тем, чтобы скопированная кнопка была размещена по голубым линиям. При копировании сохраняется соединение с нашим Action.

Screen Shot 2015-01-30 at 9.48.33 AMВам нужно поменять заголовок скопированных кнопок. Можно выделить все кнопки, при нажатом Shift и перемещать выделенное как единое целое. Лучше поместить всю группу кнопок как целое в верхних левый угол, придерживаясь голубых линий, Верхняя голубая линия покажет, что вы поместили всю цифровую клавиатуру ниже нашей метки с 0.

Итак, все кнопки посылают одно и тоже сообщение. Как определить, какая кнопка прислала сообщение? Давайте писать код внутри нашего метода, и первое, что я делаю, — это декларирую локальную переменную внутри метода.

Screen Shot 2015-01-30 at 10.06.46 AMЯ хочу получить цифру на кнопке, которая была нажата и прислала сообщение.

Начинается декларация со слова let. Что такое let? Есть var, это понятно variable. let — это то же самое, что и var, за исключением того, что она константа. Это означает, что digit никогда не будет изменена в этом методе. Мне очень нравится такая возможность, потому что она существенно увеличивает читабельность кода: я точно буду знать, что digit никогда не будет изменена, и даже если метод будет иметь более сотни строк, мне не нужно их просматривать на предмет возможного изменения digit. Вы будете удивлены насколько знание того, что это локальная переменная, что она- константа, увеличивает читабельность кода.

ВОПРОС: А не нужно ли увеличить читаемость кода тем, как в Java, и писать константы только заглавными буквами? Может быть следовать такому соглашению при назначении имен?

ОТВЕТ: Это можно отнести к стилю программирования, но в Swift так не делают и я через секунду покажу вам почему. Потому что в Swift вы можете просто кликнуть на любом символе где угодно и получить полную информацию о том, как этот символ был задекларирован. Вы это увидите.

Информацию для digit я буду получать от кнопки sender. Но мне нужно спросить ее : «Какой у тебя заголовок?» Для этого я должен послать sender сообщение. И сейчас самое время поговорить о документации. Потому что если вы хотите быть хорошим iOS разработчиком, то вам нужно очень хорошо ориентироваться в документации. К счастью, документация очень удобно подключена к  Xcode. Например, если я хочу найти информацию о UIButton, нужно навести мышку на что-то, удерживая клавишу Option. Если информация есть, то появится голубая пунктирная подчеркивающая линия, а указатель мышки превратится в знак вопроса ?. И если вы кликните, то появится информация о классе UIButton.

Screen Shot 2015-01-30 at 10.59.44 AMЭта всплывающее окно дает краткую информацию о класса : о супер классе, о протоколах, краткое описание. Но внизу есть ссылка на полное описание этого класса. Если я кликну на эту ссылку, то получу детальную информацию о классе.

Screen Shot 2015-01-30 at 11.04.33 AMСлева у вас приведены все переменные этого класса, то есть properties, и методы класса UIButton. Вы можете кликнуть на любом из них и получите полное описание
Просматривая информацию об этом классе, я могу кликнуть на свойстве currentTitle  и посмотреть его описание.

Screen Shot 2015-01-30 at 11.12.13 AMВернемся в код. Имея sender, как нам получить доступ к его переменным и методам? Используя точку . . Такой синтаксис используется во многих языках. Как только мы поставим точку после digit, Xcode выдаст всю информацию, которая ей известна об UIButton.

Screen Shot 2015-01-30 at 11.17.59 AMА знает она очень много. Я нахожу интересующий меня currentTitle. Заметьте, что когда я начинаю набирать интересующую меня строку, то справочная система оставляет только то, что соответсвует набранному мной фрагменту текста. Если я еще не набрала целиком слово, а оно одинаковое у всех, то нажав Tab, одинаковый фрагмент дополнит мой набранный текст.

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

Screen Shot 2015-01-30 at 11.35.32 AM

Давайте запустим приложение. Начнем нажимать наши цифры. При первом же нажатии внизу появится консоль, на которой можно смотреть результат.

Screen Shot 2015-01-30 at 11.40.44 AM

Но что мы видим? Какие-то Optional?

Понимание Optional имеет решающее значение в понимании логики Swift. Пожалуй, это наиболее важное понятие, которое вначале людям не так-то легко принять.  Мы сосредоточимся на том, чтобы правильно понимать значение Optional. Давайте вернемся к нашему коду. Между прочим, вы можете регулировать появление и скрытие консоли специальной кнопкой, которая располагается там же, где располагаются кнопки, регулирующие появление и скрытие Навигатора и Области Утилит. Но можно убрать консоль простым перетягиванием ее вниз. Иногда удобно, чтобы консоль присутствовала постоянно.

Но вернемся к Optional. Во-первых, не находите ли вы странным, что у digit не указан тип?  Видите? Я не указал тип digit. Что, Swift не требует типизации переменных? Нет, наоборот, Swift  — язык с очень строгой типизацией. Все переменные имеют тип. Вы обязаны указать тип. Но Swift замечателен тем, что называется type inference («вывод типа»). Он может вывести тип из контекста. Я указал, что digit равен … .currentTitle и Swift сделал digit того же типа, что и currentTitle.
Что же это за тип? Если вы будете держать клавишу Option, как при поиске документации,  и кликните на вашей собственной переменной, то увидите, является эта переменная константой или переменной, и какого она типа. Делаем это и видим, что digit  имеет тип String?. Этот знак вопроса и означает, что тип является Optional.
Screen Shot 2015-01-30 at 1.29.40 PM

Optional это такой тип, который может иметь два значения. Одно значение — это то, что значение не установлено и мы называем это значение nil. И в Swift это единственное значение nil — показывать, что Optional значение не установлено.
Другое значение, которое может принимать Optional переменная — это something (что-то) и тип этого самого something тип без вопросительного знака. В нашем случае это String. Если мы видим тип String?, то будем говорить, что это тип Optional String. То есть, если значение установлено, то тип его String. В действительности String? это не строка, которая может быть nil , а это Optional строка, которая может быть String. Это очень важное предложение для понимания.
Итак,digit получила тип String? потому, что currentTitle возвращает этот тип. Давайте посмотрим.

Screen Shot 2015-01-30 at 1.52.53 PMНам показывают документацию, и мы видим, что var currentTitle  является переменной экземпляра класса UIButton  и имеет имя currentTitle и тип String?  {get} означает, что эта переменная только для чтения ( read-only ). Я не вижу { set }, следовательно мы не можем установить это свойство. Эта переменная Optional и она всегда будет Optional. Все это прекрасно, но как я получу строку? Я не хочу, чтобы она была  Optional. И способ это сделать состоит в развертывании (unwrap) Optional значения с помощью восклицательного знака ! и получении ассоциированного значения. Давайте посмотрим, что произойдет с digit, если я буду возвращать значение со знаком !.

 

Screen Shot 2015-05-18 at 6.20.55 PM

Видите? digit больше не Optional.  digit превратилась в обычную String, так как мы ее «развернули».  Но что произойдет, если currentTitle не получит строку? Ее значение будет nil , и произойдет аварийное завершение (crash). Другими словами, если вы используете знак для «разворачивания» Optional значения и текущее значение не установлено, то есть имеет значение nil, то программа аварийно закончится.
Многие подумают, что сейчас я везде наставлю  Optional значения и моя программа не будет аварийно завершаться, потому что в iOS множество  Optional значений. Для многих вещей можно установить Optional значения, так как они могут быть в состоянии «не установлены»  некоторое время.

Но, возможно, в нашем случае вы захотели бы, чтобы программа закончилась аварийно, потому что у вас есть кнопка, у которой не установлен заголовок и она посылает сообщение вашему Controller. Возможно, вы захотите найти эту ошибку, прежде чем поставите вашу программу в AppStore. Вот почему иногда аварийное завершение — это хорошо. Если вы не хотите, чтобы программа аварийно завершалась. то есть способ это сделать и я покажу как, немного позже.
Но сейчас вы должны понять, что знак «разворачивает» Optional значение и происходит аварийное завершение программы, если значение не установлено, то есть равно nil. Но если оно не nil , то оно получает строку. Давайте запустим наше приложение.

Screen Shot 2015-01-30 at 2.59.42 PMЗдесь больше нет Optional.

Теперь посмотрим, что мы хотим делать с полученными  цифрами. Мы хотим добавить их в конец нашего дисплея.

Если у нас есть документация, то смотрим документацию по UILabel, так как display имеет тип UILabel. И видим,  что UILabel  имеет свойство text, оно имеет тип String?, потому что текст на метке может быть не установлен.

Screen Shot 2015-01-30 at 3.17.40 PM

Я хочу установить  свойство text ,и могу  установить его в  nil , так как оно — Optional. Это законно, и вы видите, что нет никакого сообщения об ошибке, никакого предупреждения. Таким образом я «очищу» мой дисплей, он не будет установлен. Но я могу установить его в строковое значение, так как тип  text  это String?Я добавляю полученную цифру digit к уже существующему значению текста дисплея display. text .

Screen Shot 2015-01-30 at 3.28.54 PM

И получаю ошибку. Потому что display.text имеет тип Optional String String?, а не String. Нам необходимо «развернуть» (unwrap) текст на дисплее в String, потому что складывать мы можем только строки. И опять, если дисплей окажется не установлен, то у нас произойдет аварийное завершение. Давайте запустим приложение.

Screen Shot 2015-01-30 at 3.59.09 PMНажимаем 8, 9, 6. Все работает. Но не нравится лидирующий 0.

Когда я вначале начинаю печатать 8, мой Controller должен знать, что я только что начал печатать число, и 0 должен быть заменен на 8.  Если я нахожусь в середине печати моего числа, то цифры должны добавляться к тексту на дисплее, если я нахожусь вначале, то цифра на дисплее должна быть заменена.
Для этого добавим свойство userIsInTheMiddleOfTypingANumber типа Bool. Вы можете подумать: «Ужасное имя. Я должен его набирать мног раз.» Но это последний раз, когда я напечатал его полностью, потому что Xcode всегда будет стараться заполнить его за меня. Так что длинные имена — это прекрасно. И мне нравится мое длинное имя userIsInTheMiddleOfTypingANumber.

Screen Shot 2015-01-30 at 4.48.52 PM
Но мы получили ошибку. Иногда вы получаете совершенно непонятную ошибку, потому что недостаточно изучили Swift. То, что мы получили — одна из них. Эта ошибка говорит о том, что у вашего класса ViewController  нет инициализатора. И это потому, что в  Swift , ВНИМАНИЕ, все свойства должны быть инициализированны при инициализации самого объекта. У вас не может быть свойства, которые пребывает в не инициализированном состоянии. Если это свойство — Optional, вы можете его установить в nil. Но свойство обязательно должно получить какое-то значение. У свойства класса ( а вы помните, что это переменная экземпляра класса) есть два способа получить значение. Один способ — с помощью инициализатора, К сожалению, я не буду учить вас этому до следующей недели. Другой способ — присвоить конкретное значение свойству. В нашем случае false.  

Screen Shot 2015-01-30 at 5.07.42 PM

Видите? Мы избавились от ошибок.  Теперь, если мы находимся в середине набора числа userIsInTheMiddleOfTypingANumber == true, то мы делаем то, что и раньше — добавляем цифру в конец строки дисплея. Если мы находимся в начале набора числа userIsInTheMiddleOfTypingANumber == false, то мы помещаем в дисплей только эту цифру и указываем, что сейчас мы уже находимся в середине набора числа.

Screen Shot 2015-01-30 at 5.14.40 PM

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

Screen Shot 2015-01-30 at 5.22.48 PM

Итак, мы создали калькулятор, который выводит цифры на дисплей. В следующий раз мы заставим наш калькулятор считать.

ВОПРОС: Почему мы не инициализируем display:UILabel! ?
ОТВЕТ: Это фантастический вопрос, и я собираюсь об этом говорить в Среду. Я расскажу, почему здесь знак  ! , а не ? Но почему display— это Optional? Мы поговорим об этом в следующий раз.

 

 

Лекция 1 CS193P Winter 2015 — Логистика курса, обзор iOS 8. (часть 2): 25 комментариев

  1. Спасибо за перевод! Всё предельно понятно. Очень надеюсь, что вы продолжите переводить лекции.

  2. Спасибо за перевод!
    Правильно я понял что лекции выкладываются только на iTunes, а на Piazza людям не из Cтэнфорда не попасть? То есть нет нигде больше мест где люди проходящий этот курс собираются?

    • На Piazza можно попытаться попасть. На iTunes найдите «Coding Together: Developing iOS 6 Apps for iPhone and iPad (Winter 2013)». В описании курса есть Enroll Piazza. Я не знаю, может быть работает, но это не для студентов Стэнфорда, а для таких как мы. Но так как нет туда приглашения, то посетителей сейчас мало, но можно задать вопрос. Можно найти интересные материалы. Но официального места нет.

  3. Спасибо за перевод и хорошее оформление!
    Прочитал на одном дыхании, все очень хорошо описано и понятно.
    Жду перевода остальных лекций, заранее благодарю.

  4. Просьба добавлять условия домашних заданий. Хочется прогать, а потом сравнивать решения.

    • Домашнее задание выложу. А как и где вы собираетесь сравнивать? Я тоже хотела бы это как-то организовать, но не ни опыта, ни времени.

  5. Большущее спасибо, все понятно, очень интересно,
    колоссальный труд!!!

  6. На картинке после слов «Давайте посмотрим, что произойдет с digit, если я буду возвращать значений со знаком !.» неправильно обведен восклицательный знак!
    Нужный восклицательный знак находится на три строки ниже после currentTitle

    Спасибо за перевод!

  7. Огромнейшее СПАСИБО! за труды. Вы очень помогаете тем, у кого проблемы с английским языком.

  8. Спасибо большое за перевод Таня.
    Почему профессор выбрал такой путь userIsInTheMiddleOfTypingANumber == false а потом менять на true?
    Почему не проверить сразу if resultLabel.text == «0»
    if resultLabel.text == «0» {
    resultLabel.text = curretnValueFromButton
    } else {
    resultLabel.text = resultLabel.text! + curretnValueFromButton
    }

    • Если вы захотите начать набор числа сначала, то следуя вашей логики, вам придется установить дисплей в 0. Профессор устанавливает в false, а вы в 0. Он избрал более общий случай, так как начальное значение может оказаться вовсе не 0, а, например, пусто.

  9. Спасибо, Татьяна, за Вашу работу! И Полу Хэгарти, разумеется, тоже. У меня в ВУЗе было только два преподавателя, на столько же доступно и качественно объяснявших предмет.

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

  11. Добрый день. Проблема выходит, когда нажимаю на любую кнопку на UI моем, то симулятор приостанавливается и выходит сообщение Thread 1 breakpoint 2.1
    Благодарю заранее )

    let digit = sender.currentTitle! || Thread 1: breakpoint 2.1

    • Не видя кода и не зная для какой iOS (iOS 7, 8, 9) вы пишите приложение, невозможно чем-то вам помочь.
      Вы должны поделиться вашим кодом либо через Github, либо Dropbox, либо другим каким-то способом.

  12. Написал в точности так же, как в примере. Однако, калькулятор работает не корректно. При нажатии первый раз любой цифры — выводится одна цифра. Все последующие нажатия выводят на дисплей не по одной цифре, а сразу по две.
    Например: 1223344 или 4778899
    не могу понять почему

  13. Хочу поблагодарить автора перевода. Большое спасибо, пока нигде более понятного изложения  swift и code не встречал.
    Надеюсь вы продолжите переводить лекции, они понятнее любого учебника.

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