UIKit 1 / 1.2. Цели распространения, виды ошибок


Видео


− С новым годом, блин, − Слава полетел к приборной панели – говорил же, что что−то не то. Корабль затрясся снова, свет полностью вырубился, датчики топлива вдруг резко замерцали красным. – да что ж за фигня такая?
− Саша, проверь двигательный отсек, топлива нет, а я только сегодня пополнял.
− нифига не вижу, дверь заклинило.
− Черт, − Слава направился в сторону голоса, − подвинься, иди в приборную, следи за датчиками. −Коля, ты там заснул, мать твою? Быстро помоги мне. Коля оцепенело водил глазами и не двигался с места. – ты глухой что ли? – заорал Слава, продолжая толкать дверь. Вдруг свет включился, корабль перестало трясти, дверь в энергетический отсек открылась.
Слава начал проверять уровень топлива в баках. Странно, еще утром все было нормально, а сейчас ощущение, что где−то в корабле дыра. Пока Слава думал, как это выяснить, в голове появлялись нехорошие мысли. Коля слишком часто жаловался на условия, был всем недоволен и всячески отлынивал от заданий.
− ах ты сука, решил домой побыстрее попасть? А о том, что мы все сдохнем не потрудился подумать? – Слава резко развернулся к двери, из которой все еще было видно оцепенелого Колю. – я щас тебя без скафандра за борт выкину и будешь дыру латать! − Похоже эти слова привели Колю в чувство, он резко подлетел к двери и захлопнул ее. Из−за двери послышались голоса девчонок:
− Коля, ты что, рехнулся, быстро дверь от……
И тут резкий безумно громкий взрыв прогремел рядом. Всё потемнело.


Обучение не бывает без проб множества идей и провала множества раз.

Сэр Джонатан Айв

В этом уроке


Цели распространения

Наверху окна очень удобное меню. Оно показывает для какого конкретно устройства Вы соберёте проект или какой симулятор запустить.

Наверху будут показаны устройства, подключенные к macOS, а ниже - доступные симуляторы. Если Ваше устройство не особо сильное, то используйте старые устройства наподобие iPhone SE для минимального воздействия на macOS.

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

Чтобы менять ориентацию устройства, используйте Cmd + Стрелка влево и Cmd + Стрелка вправо

Чтобы менять масштаб, используйте Cmd + Число(1…5).

Чтобы полностью выйти из симулятора, нажмите Cmd + Q. Чаще Вам просто нужно заново запустить приложение. Если Вы работаете, будучи подключенными к сети электропитания, то оставьте симулятор запущенным. Просто нажмите Cmd + ., чтобы закрыть приложение, но оставить сам симулятор активным.

Симулятор подходит не для всех приложений - взаимодействие с камерой, например, убьёт Ваше приложение, ибо у симулятора нет камеры.

Каким бы он не был удобным, всегда проводите тесты и на реальном устройстве.

Для запуска на реальном устройстве выберите его из списка и запустите. С первого раза запуск скорее всего не выйдет: нужно дать доверие Вашему аккаунту разработчика. Конкретные инструкции будут показаны непосредственно на устройстве.


Наше приложение

Сперва откроем файл ViewController.swift.
Изучим немного его строение.

Наверху идёт импорт библиотеки UIKit - эта библиотека предназначена для создания графических элементов мобильных приложений. Её аналогом для macOS выступает AppKit. В macOS используется фреймворк Cocoa, в iOS - Cocoa Touch. Многие их элементы крайне схожи, однако их подходы различаются. Этот курс посвящён Cocoa Touch.

Далее идёт объявление класса ViewController - наследника класса UIViewController, который отвечает за управление отображением единственного окна приложения.

Он содержит два метода:

Чтобы больше понять об утечках памяти, запустите мощную игру на компьютере под Windows (Skyrim, Witcher 3, Fallout 4) и попробуйте измерить занимаемый объем памяти в начале запуска и спустя много часов работы. Вы заметите, что он очень сильно возрос и помогает только перезапуск игры или системы в целом. Даже крупные программы имеют свойство создавать утечки памяти - ситуации, когда память занимают объекты, которые уже не используются и никогда уже не будут использованы. Раньше такое поведение встречалось часто - в языке C выделение памяти крайне рутинный процесс с ручным заданием объёмов, в старых стандартах C++ механизм был чуть лучше, но программисту всё равно приходилось думать об освобождении ресурсов, затем были добавлены уникальные и разделяемые указатели, а в Objective-C несколькими годами ранее придумали изученный нами автоматический механизм подсчета ссылок.

Оба этих метода вызывают варианты надкласса, так как UIKit уже берет на себя очень большой кусок по обработке этих ситуаций.


Виды проблем

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

Рассмотрим разные виды ошибок.

Предупреждения

Предупреждения (Warning) или же варнинги - возникают при сборке кода и их проще всего исправить. Они не помешают коду быть собранным и даже работать без логических ошибок, однако считается лучшей практикой исправлять все предупреждения. Очевидные варианты предупреждений:

Давайте создадим предупреждение: впишите в методе viewDidLoad() код let x = 11.

Будет выведено сообщение с жёлтым значком треугольника с восклицательным знаком о том, что неизменяемая величина никогда не использовалась. Также тут дадут совет - заменить её имя на _ , чтобы контекст съел присвоенную величину. Когда Вы будете что-либо разрабатывать, Вам часто будет выдаваться это предупреждение, так живой (в реальном времени) поиск ошибок может работать быстрее, чем Вы пишите код.

Сотрите свой код.

Ошибки сборки/компилятора

Ошибка или исключение сигнализирует о более серьёзной проблеме, например, о невозможности собрать код.
Давайте сделаем ошибку!
Удалите закрывающую круглую скобку в вызове super.viewDidLoad().

Полученная ошибка сигнализирует: "ожидается выражение в списке выражений" ("Expected expression in the list of expressions"). Это значит, что компилятор пытается использовать код после первой круглой скобки как аргументы функции и это естественно не удаётся. Заметьте, как выглядит эта ошибка - красный восьмиугольник с восклицательным знаком.

Верните закрывающую круглую скобку.

Теперь введите код:

let x = 11
x = 61

Теперь появится другой вид ошибки - вместо восклицательного знака будет изображена точка. Такие ошибки называются исправимыми.

Щелкнув по кругу, Вы увидите предложения по исправлению ошибки - заменить квалификатор let на var. Нажмите на кнопку fix. Запомните, что такой подход не всегда дась исправить все ошибки - он позволяет исправлять лишь незначительные проблемы.

Теперь у нас вылезло предупреждение, что переменная x была сразу изменена, а её изначальное значение оказалось бесполезным. Казалось бы, ничего страшного, но переменная будет создана, что съест ресурсы памяти и процессора, хоть и временно. Научитесь мыслить в понятиях цены - у Вас есть ресурсы:

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

Не старайтесь добиться максимальной производительности в ущерб читаемости кода и переносимости - лучшим способом написать программу с минимумом ресурсов будет использование Ассемблера, однако время разработки составит огромную величину. Выигрыш при этом будет не самым лучшим - в режиме агрессивной оптимизации компилятор выдаст близкий к такому код, при этом Вам не придётся платить его развитием и своим временем.

Сотрите плоды своего творчества прежде, чем двигаться дальше.

Баги

Баги - ошибки в логике кода, которые возникают в процессе работы программы. Они условно разделяются на два типа: ошибки написания программы и ошибки моделирования бизнес логики.

Ошибки при написании программы, которые когда-нибудь обязательно выстрелят. Необязательно, что Вы найдёте их сами. При неграмотном написании кода или отсутствии тестирования может выйти так, что пользователь просто спишет с Вашего счёта деньги. Запомните: если что-то плохое может случиться, то оно обязательно рано или поздно случиться. Это можно понимать ещё и так, что если в Вашем коде есть потенциально опасная ситуация - например, что Ваш неявно извлекаемый опционал может принять значение nil, то рано или поздно он его обязательно примет.

Второй тип ошибок мы не сможем рассмотреть на текущем этапе разработки. Они относятся к ошибкам моделирования бизнес-логики - например, неверно выведенная формула для расчёта платежей. Их исправление намного сложнее - при прочих равных ни программа, ни компилятор о них Вам не сообщат.

Давайте создадим наш собственный баг, дабы научиться их выискивать: для этого напишите следующий код после вызова super.viewDidLoad():

var courses = [1, 2]
courses.removeFirst()
courses.removeFirst()
courses.removeFirst()

Соберите приложение. Всё прошло без проблем. А теперь запустите его.

У нас вылезла ошибка fatal error: can't remove first element from an empty collection (фатальная ошибка: нельзя извлечь первый элемент из пустой коллекции).
В коде будет показана точка ошибки с не самым понятным описанием. В консоли (1) же появится надпись (lldb). lldb - отладчик в приложениях под Apple, он расшифровывается как low level debugger и позволяет находить многие ошибки. Давайте убедимся, что коллекция действительно пуста. Два способа сделать это:

Прежде, чем двигаться дальше, обратите внимание, что наша область слева перешла с навигатора на отслеживание программы. Там можно увидеть нагрузку на процессор в реальном времени, на диск, занимаемую оперативную память, сетевое взаимодействие. Вы можете использовать эти показатели лишь в относительном виде - симулятор не показывает реальных данных из-за принципа виртуализации. При отладке на реальном устройстве Вы также сможете увидеть эти показатели, и здесь они уже более достоверны. Учтите, что программа для отладки и релиз-вариант отличаются по своей сборке - как правило, релизный вариант быстрее варианта для отладки на некоторую величину ввиду дополнительных механизмов оптимизации.

Теперь попробуем найти момент, где возникла ошибка. Сперва отпустите наше приложение в мир иной уже известной нам командой Cmd + ..

Щёлкните по номеру строки около объявления массива. Появится синяя фигура - брейкпоинт или точка останова. Пусть будет брейкпоинтом. Мы же не на 1С пишем, чтобы извращать наш язык. Чтобы убрать точку останова снова нажмите по ней (сделайте это в конце занятия). Это выключит её, но не удалит - для удаления нажмите по ней правой кнопкой и выберите Delete breakpoint.

Теперь запустите наше приложение. Наша строка будет отмечена зелёной - ход нашей программы остановился в этой точке. Как можно заметить, переменная courses всё ещё пуста. Нажмите на 4-ую слева иконку на панели отображения переменных. Это переместит выполнение программы на один шаг вперёд. Эта кнопка называется Step over.

И всё равно всё замечательно - в массиве два значения. Переместитесь на ещё один шаг вперёд.

Аналогично, в массиве остался один объект. Заметьте, что зелёная линия говорит о том, что мы находимся в точке выполнения этой инструкции, однако инструкция ещё не выполнена.
Продолжим путь.

Ошибки не возникло. Однако впереди ещё одна инструкция, а наш массив уже пуст. Чувствуете витающее в воздухе напряжение и предчувствие беды? Продолжаем.

А вот и наша ошибка. Благодаря проделанной нами работе, стало ясно, что ошибка возникает, когда мы пытаемся в третий раз извлечь элемент из коллекции, которая изначально имела всего 2 элемента.

Убейте приложение. Удалите код, внесённый нами. Отключите брейкпоинт.


Как работать с ошибками

Теперь Вы готовы понять главную мудрость этого урока:

  1. Если возникла ошибка, то сперва поймите, в чём же проблема - она не всегда возникает в том месте, где приложение перестаёт работать. Хуже всего - она очень редко возникает в видимом месте.
  2. Найдите решение проблемы - часто, чтобы быстрее закончить работу, программисты пользуются костылями (мы уже знакомились с ними в первом курсе). Однако в долгосрочной перспективе использование решений-затычек лишь приведет к прогрессивной деградации приложения.
  3. Проверьте решение. Если всё хорошо, то значит Вы научились на своих ошибках.
  4. Бейтесь головой о Ваш чудесный 5K экран, пока не найдёте решение проблемы.