Как пользоваться утилитой Instruments в Xcode

Xcode
ТипСреда разработки программного обеспечения
Разработчик Apple Inc.
Операционная система Mac OS X 10.3 (Версия 1.x) Mac OS X 10.4 (Версия 2.x) Mac OS X 10.5 (Версии 2.5, 3.0, 3.1) Mac OS X 10.6 (Версии 3.2, 4.0, 4.1, 4.2) OS X 10.7 (Версии 4.1, 4.2, 4.3, 4.4, 4.5, 4.6) OS X 10.8 (Версии 4.4, 4.5, 4.6, 5.0) OS X 10.9 (Версии 5.0, 5.1, 6.0, 6.2) OS X 10.10 (Версии 6.0, 6.1, 6.3, 6.4, 7.0) OS X 10.11 (Версия 7.0)
Последняя версия 7.3 (7D175) (21 марта 2016)
Лицензия Смешанное проприетарное и copyleft программное обеспечение
Сайт [developer.apple.com/tools/xcode/ er.apple.com/tools/xcode/]

К:Википедия:Статьи без изображений (тип: не указан)
Xcode

— интегрированная среда разработки программного обеспечения под OS X и iOS, разработанная корпорацией Apple. Первая версия выпущена в 2001 году. Стабильные версии распространяются бесплатно через Mac App Store. Зарегистрированные разработчики также имеют доступ к бета-сборкам через сайт [developer.apple.com Apple Developer]

Описание

Xcode включает в себя большую часть документации разработчика от Apple и Interface Builder — приложение, использующееся для создания графических интерфейсов.

Пакет Xcode включает в себя изменённую версию свободного набора компиляторов GNU Compiler Collection и поддерживает языки , C++, Objective-C, Objective-C++ (англ.)русск., Swift, Java, AppleScript, Python и Ruby с различными моделями программирования, включая (но не ограничиваясь) Cocoa, Carbon и Java. Сторонними разработчиками реализована поддержка GNU Pascal[1], Free Pascal[2], Ada[3], [4], Perl[5], Haskell[6] и [7]. Пакет Xcode использует GDB в качестве back-end’а для своего отладчика.

В августе 2006 Apple объявила о том, что DTrace, фреймворк динамической трассировки от Sun Microsystems, выпущенный как часть OpenSolaris, будет интегрирован в Xcode под названием Xray. Позже Xray был переименован в Instruments.

4) Область редактора (Editor)

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

Как уже отмечалось, клик по файлу открывает содержимое для редактуры. Но это не единственный способ добраться к файлам кода.

Навигация в области редактора

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

Еще один способ быстро перейти к искомому файлу — функция Jump Bar

(см. изображение)
.
С помощью Jump Bar вы можете быстро просмотреть группы и найти нужный файл.

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

Если кликнуть по хвостовому сегменту Jump Bar, откроется меню с методами в файле. Это не только позволит перейти в другой раздел файла, но и покажет, какие методы доступны в этом файле.

Три вида окна редактора

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

Кнопка слева — для работы в режиме одного лишь редактора, что больше подходит для лэптопов с маленькими экранами, когда нет внешнего монитора.

Средняя кнопка — опция помощник редактора (Assistant Editor), показывает дополнительный файл текущего файла в формате разделенного экрана. К примеру, если слева файл ViewController.swift, в окне справа будет файл соответствующего класса для ViewController. В каждой панели есть опция быстрого перехода (jump bar). С ее помощью можно изменить то, что показывается в каждом файле.

Правая кнопка — редактор версии (Version Editor), в котором можно сравнить два разных файла; больше информации об этой функции в Apple Documentation.

Окно конструктора интерфейса

До сих пор речь шла о редактуре файлов с кодом и написании кода, но в Xcode интегрирован конструктор интерфейса, в котором вы можете просматривать Storyboard или файлы XIB. Область редактора становится визуальным конструктором.

Поиск и замена в файле

Нажмите Command-F, чтобы вызвать поисковое окно в верхнем правом углу, которое будет искать то, что вы вписываете в текущем файле. Это также хороший способ перейти к различным областям вашего файла или что-либо изменить в нем.

Переход к определениям

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

Контрольные точки

Здесь (см. изображение) вы можете установить контрольные точки/точки останова в определенных линиях кода. Устанавливая эти точки, вы заметите индикатор синего цвета. Чтобы отменить контрольную точку, кликните по синему индикатору — он станет темнее.

Если кликнуть и перетащить синий индикатор, контрольная точка полностью удалится.

Просмотреть список всех контрольных точек проекта можно с помощью вкладки навигатор контрольных точек в области навигатора.

Xcode 4

С 9 марта 2011 года стала доступна новая версия Xcode 4, причем в новую версию входят наборы SDK OS X 10.6 и SDK iOS 4.3[8]. Впервые предварительный релиз Xcode 4 был показан на WWDC 2010.

В Xcode 4 был представлен новый пользовательский интерфейс: единое окно, куда встроен и Interface Builder, сам Xcode, Instruments, помощник, новая система анализа кода Debug Console с более сильным движком, облегчающая исправление ошибок и осуществляющая поиск логических проблем в коде. Программа также получила дополнительный компилятор Apple LLVM.

О типах файлов в Xcode

Рассмотрим здесь типы файлов Xcode, с которыми придётся столкнутся в ближайшем будущем. Для их изучения рассмотрим панель или область навигатора в Xcode (номер 3 на рисунке выше).

Верхний файл с типом .xcodeproj- файл проекта Xcode, чтобы перейти в его настройки (в которых мы и так находимся), выберите его.

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

.storyboard — файлы раскадровок или историй. Каждое приложение в Xcode представляет собой пользовательскую историю — как будет пользователь взаимодействовать с программой. Такая ориентация на разработку приложений под потребности пользователя выгодно отличает данную среду от многих других, зацикленных на создании кода ради кода. Основной принцип Swift и Apple — «Write less, do more» («Пиши меньше, делай больше»): Вам не придётся тратить много времени на написание самого кода — большую часть времени Вы будете разрабатывать модель и бизнес-логику приложения. Такой подход позволяет Вашим приложениям лучше удовлетворять потребности клиентов, а значит и Вам получать больше прибыли.

.xcassets — каталог даст Вам возможность собрать в одном месте ресурсы приложения — иконки, изображения, звуки и тому подобное. Ещё одна польза подхода — Вы можете задать разные размеры изображений под различные экраны, а в коде использовать абстрактный вид изображения без привязки к размерам.

.plist — propertylist — список свойств — специальные файлы для настройки приложений или хранений ассоциативной информации. Если Вы работали на Windows с настройками программ, то часто попадались файлы типа .ini- аналоги списков свойств, однако списки свойств более структурированы и эффективны. Info.plist содержит настройки приложения, которые Вы задаёте через графическое меню.

Xcode 8

С 13 сентября 2020 года стала доступна бета-версия нового Xcode 8. В ней появилась поддержка iOS 10, Swift 3.0, обновленный и расширенный дебаггер.

История версий

Версия 1.x

  • 1.0 (осень 2003)
  • 1.5

Версия 2.x

  • 2.0
  • 2.1
  • 2.5

Версия 3.xx

  • 3.0
  • 3.1
  • 3.2
  • 3.2.6

Версия 4.xx

  • 4.0 (9 марта 2011 года)
  • 4.1 (20 июля 2011 года; только для Mac OS X 10.6, 29 августа 2011 года для Mac OS X 10.7)
  • 4.2 (12 октября 2011 года)
  • 4.3 (7 марта 2012 года)
  • 4.3.2 (22 марта 2012 года)
  • 4.3.3 (май 2012 года)
  • 4.4 (25 июля 2012 года)
  • 4.4.1 (7 августа 2012 года)
  • 4.5 (19 сентября 2012 года)
  • 4.5.1 (3 октября 2012 года)

Версия 5.xx

  • 5.0 (12 сентября 2013 года)
  • 5.0.1 (4 октября 2013 года)
  • 5.0.2 (11 ноября 2013 года)
  • 5.1 (10 марта 2014 года)

Версия 6.xx

  • 6.0 (9 сентября 2014 года)
  • 6.1.1 (2 декабря 2014 года)
  • 6.3.1 (19 апреля 2020 года)
  • 6.3.2 (18 мая 2020 года)
  • 6.4 (30 июня 2020 года)

Версия 7.xx

  • 7.0 (16 сентября 2020 года)
  • 7.1 (21 октября 2020 года)
  • 7.1.1 (9 ноября 2020 года)
  • 7.2 (8 декабря 2020 года)

Xcode 9

С 19 сентября 2020 года стала доступна версия нового Xcode 9. В ней добавлена возможность отладки в беспроводном режиме, появилась поддержка новой версии языка программирования Swift 4 и SDK для новых ОС Apple: iOS 11, macOS High Sierra 10.13 и watchOS 4. Так же в этой версии появилась поддержка обновлённого графического движка для «почти прямой» работы с GPU — Metal (англ.)русск. 2[15] и впервые появились такие новые фреймворки как: ARKit (англ.)русск. — для использования дополненной реальности и Core ML (англ.)русск. — для машинного обучения и построения нейронных сетей[16].

Примечания

  1. [www.microbizz.nl/gpcxcode.html GNU Pascal and Xcode]
  2. [pascal-central.com/fp-xcode/ Using Free Pascal with Xcode]
  3. [pyrite.truman.edu/~millerj/AdaonOSX/ Ada on OS X]
  4. [code.google.com/p/cocoa-sharp-dev/wiki/CSharpPlugin CSharpPlugin for Xcode]
  5. [camelbones.sourceforge.net/index.html CamelBones, an Objective-C/Perl bridge for Mac OS X & GNUStep]
  6. [hoovy.org/HaskellXcodePlugin/ Haskell Xcode Plugin]
  7. [michelf.com/projets/d-pour-xcode/ D pour Xcode]
  8. [www.cybersecurity.ru/software/117223.html Apple сегодня официально выпустила Xcode 4]. // CyberSecurity.ru
  9. [developer.apple.com/technologies/tools/whats-new.html What’s New in Xcode 5]. // Официальный сайт Apple
  10. [www.3dnews.ru/821432 iOS 8 SDK содержит свыше 4000 новых API]. // 3DNews

9) iOS-эмулятор

К Xcode 8 прилагается несколько полезных эмуляторов для тестирования. Более того, большую часть времени разработки вы можете использовать эмуляторы, а для тестирования, когда уже практически все сделано, выбрать смартфон или планшет.

В частности, эмулятор позволяет:

  • Менять расположения экрана (ландшафтный/портретный режимы)
  • Моделировать различные GPS-координаты
  • Моделировать сценарии с низким объемом памяти

(С выходом версии Xcode 6.3 появился эмулятор Apple Watch для тестирования приложений под эту ОС).

Литература

  • Мэтт Нойбург.
    Программирование для iOS 7. Основы Objective-C, Xcode и Cocoa = iOS 7 Programming Fundamentals: Objective-C, Cocoa, and Xcode Basics. — М.: «Вильямс», 2014. — 384 с. — ISBN 978-5-8459-1895-6.
/C++ Borland C++ • C++ Builder • Code::Blocks • CodeLite • wxDev-C++ • Pelles C • Oracle Solaris Studio • QDevelop • Qt Creator • Ultimate++ • Microsoft QuickC
Бейсик PowerBASIC • Turbo Basic • Visual Basic • QBasic • QuickBASIC • PureBasic
Java WebLogic • BlueJ • DrJava • Greenfoot • JCreator • JDeveloper • JBuilder • JGRASP • Android Studio • Eclipse • NetBeans
Паскаль Delphi • Lazarus • MSE • PascalABC.NET • MIDletPascal • PocketStudio • Morfik • Turbo Pascal • QuickPascal • Visible Pascal
PHP Aptana Studio with PHP plugin • Delphi for PHP (RadPHP) • Eclipse PDT • Zend Studio • NuSphere PhpED • PHP Expert Editor • phpStorm • Dreamweaver
Python Boa Constructor • Eclipse+PyDev • Eric • IDLE • Komodo • PyCharm • PyScripter • SPE • Wing IDE
ActionScript Adobe Flash • Adobe Flash Builder • FlashDevelop • CodeDrive • Eclipse FDT • Realaxy ActionScript Editor
Ruby RubyMine

Отрывок, характеризующий Xcode

Надежды на исцеление не было. Везти его было нельзя. И что бы было, ежели бы он умер дорогой? «Не лучше ли бы было конец, совсем конец! – иногда думала княжна Марья. Она день и ночь, почти без сна, следила за ним, и, страшно сказать, она часто следила за ним не с надеждой найти призкаки облегчения, но следила, часто желая найти признаки приближения к концу. Как ни странно было княжне сознавать в себе это чувство, но оно было в ней. И что было еще ужаснее для княжны Марьи, это было то, что со времени болезни ее отца (даже едва ли не раньше, не тогда ли уж, когда она, ожидая чего то, осталась с ним) в ней проснулись все заснувшие в ней, забытые личные желания и надежды. То, что годами не приходило ей в голову – мысли о свободной жизни без вечного страха отца, даже мысли о возможности любви и семейного счастия, как искушения дьявола, беспрестанно носились в ее воображении. Как ни отстраняла она от себя, беспрестанно ей приходили в голову вопросы о том, как она теперь, после того, устроит свою жизнь. Это были искушения дьявола, и княжна Марья знала это. Она знала, что единственное орудие против него была молитва, и она пыталась молиться. Она становилась в положение молитвы, смотрела на образа, читала слова молитвы, но не могла молиться. Она чувствовала, что теперь ее охватил другой мир – житейской, трудной и свободной деятельности, совершенно противоположный тому нравственному миру, в который она была заключена прежде и в котором лучшее утешение была молитва. Она не могла молиться и не могла плакать, и житейская забота охватила ее. Оставаться в Вогучарове становилось опасным. Со всех сторон слышно было о приближающихся французах, и в одной деревне, в пятнадцати верстах от Богучарова, была разграблена усадьба французскими мародерами. Доктор настаивал на том, что надо везти князя дальше; предводитель прислал чиновника к княжне Марье, уговаривая ее уезжать как можно скорее. Исправник, приехав в Богучарово, настаивал на том же, говоря, что в сорока верстах французы, что по деревням ходят французские прокламации и что ежели княжна не уедет с отцом до пятнадцатого, то он ни за что не отвечает. Княжна пятнадцатого решилась ехать. Заботы приготовлений, отдача приказаний, за которыми все обращались к ней, целый день занимали ее. Ночь с четырнадцатого на пятнадцатое она провела, как обыкновенно, не раздеваясь, в соседней от той комнаты, в которой лежал князь. Несколько раз, просыпаясь, она слышала его кряхтенье, бормотанье, скрип кровати и шаги Тихона и доктора, ворочавших его. Несколько раз она прислушивалась у двери, и ей казалось, что он нынче бормотал громче обыкновенного и чаще ворочался. Она не могла спать и несколько раз подходила к двери, прислушиваясь, желая войти и не решаясь этого сделать. Хотя он и не говорил, но княжна Марья видела, знала, как неприятно было ему всякое выражение страха за него. Она замечала, как недовольно он отвертывался от ее взгляда, иногда невольно и упорно на него устремленного. Она знала, что ее приход ночью, в необычное время, раздражит его. Но никогда ей так жалко не было, так страшно не было потерять его. Она вспоминала всю свою жизнь с ним, и в каждом слове, поступке его она находила выражение его любви к ней. Изредка между этими воспоминаниями врывались в ее воображение искушения дьявола, мысли о том, что будет после его смерти и как устроится ее новая, свободная жизнь. Но с отвращением отгоняла она эти мысли. К утру он затих, и она заснула. Она проснулась поздно. Та искренность, которая бывает при пробуждении, показала ей ясно то, что более всего в болезни отца занимало ее. Она проснулась, прислушалась к тому, что было за дверью, и, услыхав его кряхтенье, со вздохом сказала себе, что было все то же. – Да чему же быть? Чего же я хотела? Я хочу его смерти! – вскрикнула она с отвращением к себе самой. Она оделась, умылась, прочла молитвы и вышла на крыльцо. К крыльцу поданы были без лошадей экипажи, в которые укладывали вещи. Утро было теплое и серое. Княжна Марья остановилась на крыльце, не переставая ужасаться перед своей душевной мерзостью и стараясь привести в порядок свои мысли, прежде чем войти к нему. Доктор сошел с лестницы и подошел к ней. – Ему получше нынче, – сказал доктор. – Я вас искал. Можно кое что понять из того, что он говорит, голова посвежее. Пойдемте. Он зовет вас… Сердце княжны Марьи так сильно забилось при этом известии, что она, побледнев, прислонилась к двери, чтобы не упасть. Увидать его, говорить с ним, подпасть под его взгляд теперь, когда вся душа княжны Марьи была переполнена этих страшных преступных искушений, – было мучительно радостно и ужасно. – Пойдемте, – сказал доктор. Княжна Марья вошла к отцу и подошла к кровати. Он лежал высоко на спине, с своими маленькими, костлявыми, покрытыми лиловыми узловатыми жилками ручками на одеяле, с уставленным прямо левым глазом и с скосившимся правым глазом, с неподвижными бровями и губами. Он весь был такой худенький, маленький и жалкий. Лицо его, казалось, ссохлось или растаяло, измельчало чертами. Княжна Марья подошла и поцеловала его руку. Левая рука сжала ее руку так, что видно было, что он уже давно ждал ее. Он задергал ее руку, и брови и губы его сердито зашевелились.

Breakpoints

Мы уже выяснили, что отладка через добавление вывода в консоль не совсем эффективна и нам нужен какой-то инструмент, который облегчит нам жизнь. Таким инструментом являются брейкпоинты. Все мы любим этот механизм, который представлен практически в любой среде разработки на любых платформах и языках, и пользуемся им. Где-то он реализован лучше, где-то хуже, но в целом Apple предоставила нам мощный и гибкий механизм точек останова. Однако, работая с разными людьми, я заметил, что пользуются ими в большинстве случаев исключительно для остановки программы — просто чтобы убедиться, что её выполнение пошло по запланированному сценарию. Иногда люди пользуются консолью отладки и командой po, но лишь в тех случаях, когда нужно разок выяснить состояние переменной. Я предлагаю рассмотреть дополнительные возможности отладчика, встроенного в нашу IDE, и привести примеры ситуаций, в которых они могут пригодиться.

Conditional breakpoints

Окно редактирования брейкпоинта

Начнём с очевидного: conditional breakpoints. Как ни странно, строка, позволяющая указать условия срабатывания брейкпоинта, всегда у нас перед глазами, но почему-то люди удивляются такой возможности. Для удивлённых самим наличием такого диалога — его можно увидеть, если дважды нажать на сам брейкпоинт. В эту строку можно записать любое выражение, которое может вернуть булево значение, будь то сравнение переменной из текущей области видимости или вовсе значение какого-то синглтона. Но будьте внимательны — медленно вычисляемое выражение способно существенно снизить производительность вашей программы.

Skipping

Следующей возможностью, которая тоже обделена вниманием разработчиков, является игнорирование N-го количества срабатываний. Эта возможность может пригодиться, например, в рекурсивных функциях, чтобы посмотреть, что происходит на N-ой глубине, или же посмотреть результат функции для N-го элемента массива. В примере с массивом этот способ будет предпочтительнее установки условия, т.к. не требует вычисления выражения.

Actions

Но самое интересное дня нас кроется за кнопкой Add Action. Эта кнопка позволяет добавить дополнительное действие, которое будет вызвано в момент срабатывания брейкпоинта. Как вы видите, есть 6 типов действий, которыми можно дополнить брейкпоинт:

  1. Apple script. Позволяет запустить скрипт на одноименном языке.
  2. Capture GPU Frame. Для отладки приложений, использующих движок Metal, может потребоваться эта опция.
  3. Debugger command. Позволяет выполнить команду отладчика. О ней мы поговорим позже.
  4. Log-message. Позволяет вывести текстовое сообщение в лог.
  5. Shell command. Позволяет выполнить произвольную команду в среде, дефолтной для системы командной оболочки, sh/bash/zsh.
  6. Sound. Позволяет проиграть звук из динамиков компьютера, на котором запущен Xcode.

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

Log message

Редактирование брейкпоинта с экшеном Log Message

Рассмотрим чуть более подробно тип дополнительного действия «Log message».

Full-Stack Разработчик

«Турбоподготовка», Москва, от 120 000 ₽

tproger.ru

Вакансии на tproger.ru

Если мы его выберем, к нашим услугам окажется строка ввода формата сообщения. Обратите внимание, что в строке можно указывать полезные плейсхолдеры, два из которых позволяют подставить информацию о брейкпоинте и одно, самое полезное, позволяет подставить результат вычисления произвольного выражения. Таким выражением может быть переменная или любая другая конструкция используемого вами языка программирования. Но это не имеет никакого смысла, если не поставить галочку «Automatically continue after evaluating actions». Именно она в паре с любым из действий позволит нам экономить время на дебаге. Больше не нужно писать print(), пересобирать проект и ждать вечность. В любой момент времени, без перезапуска проекта вам доступен вывод в консоль отладки любой информации о ходе выполнения программы. А для знающих толк в извращениях дебаге Apple предусмотрела возможность воспроизвести выражения, используя встроенный синтезатор речи.

Shell command

Редактирование брейкпоинта с экшеном shell command

Нетрудно догадаться, что этот экшен позволяет запустить произвольную команду в стандартной оболочке терминала ОС. Как и «Log message», она позволяет вычислить результат выражения в текущем контексте и дополнить им аргументы вызова команды. Для чего это может быть полезно? Примеров использования можно придумать массу. Из реальной жизни: запуск троттлинга через Charles. Необходимо было замедлять запросы из определённой точки, при этом в остальное время соединение должно было быть полноценным. Я не успевал включать-выключать троттлинг вручную и ещё совершать действия в симуляторе. Такой трюк с брейкпоинтом и «Shell command» отлично меня выручил. В другой раз мне понадобилось изменять информацию на сервере прямо параллельно с запросом, чтобы отловить довольно странный баг. Тут тоже был кстати этот вид брейкпоинта. Особые извращенцы могут собрать конструкцию на Arduino с электрошокером и бить себя током при каждом срабатывании нежелательного кода. Шучу. Не пытайтесь это воспроизвести в реальной жизни.

Debugger command

Редактирование брейкпоинта с экшеном Debugger command

Одним из самых интересных видов экшенов я считаю «Debugger command». Этот экшен позволяет действительно безгранично влиять на отлаживаемую программу. Debugger command — это команды отладчика LLDB, а LLDB — это отладчик для проекта LLVM, который сейчас используется Apple и Xcode для сборки программ. Отладчик LLDB позволяет подключаться к процессу, прерывать выполнение программы и воздействовать на её память. Для этого отладчик имеет множество команд, некоторые из которых станут героями сегодняшнего повествования. Именно благодаря отладчику LLDB у нас в принципе есть такая замечательная возможность отлаживать программу, в частности устанавливать брейкпоинты. Начнём мы с самой известной команды — po. Наверняка многие из вас уже не раз использовали эту команду при отладке, но для меня в своё время это стало открытием, хотя я уже имел некоторый опыт в разработке под iOS на тот момент. Po — это сокращение от print object. Команда позволяет вычислить выражение из правой части от команды и распечатать в консоли результат выполнения. При этом у объекта запросится его debugDescription, если он определён, или просто description, если нет. У po существует команда-прародитель — print, или p, которая точно так же вычислит выражение и распечатает результат, но только в этом случае вам будет доступна сырая информация об объекте или скалярном типе. Обе эти команды будут компилировать введенное выражение в текущем контексте, что неминуемо замедлит выполнение кода при срабатывании брейкпоинта. К счастью, в Xcode 10.2 Apple добавили ещё одну команду отладчика — v, которая работает значительно быстрее. Она позволяет вывести в консоль значение переменной из текущей области видимости, но, в отличии от p и po, без компиляции выражения. Естественное ограничение, накладываемое этой особенностью, — вывод в консоль возможен только для хранимых свойств.

Пример использования команды «v» и её ограничений

Affecting execution flow

Такая комбинация (брейкпоинт + debugger command po + автоматическое продолжение) заменит нам описанную ранее Log message. Что же ещё мы можем сделать с помощью такой комбинации? Например, с помощью дебаггера мы можем пропустить выполнение нескольких строчек кода, будто они закомментированы. При этом вам не нужно пересобирать программу и заново воспроизводить условия. Для этого достаточно ввести thread jump —by 1 для скачка вперёд на одну строчку или же thread jump —line 44 для перехода, как вы уже могли догадаться, к 44 строчке. Но будьте осторожны — вы не можете на 100% безопасно перепрыгивать по строчкам. Дело в том, что вы можете перепрыгнуть через инициализацию некоторой переменной, и это вызовет краш. Дело осложняется тем, что Swift «ленив» по своей природе, и инициализация может происходить не там, где вам кажется. Плюс компилятор при сборке вашей программы вставляет дополнительные инструкции, например для управления памятью, пропуская которые вы рискуете получить в лучшем случае утечку, в худшем — краш.

Affecting debugger

Редактирование брейкпоинта с введенной командой

Кроме влияния на вашу программу, с помощью отладчика вы можете влиять на сам отладчик. Например, мы можем поставить брейкпоинт из брейкпоинта. Вы спросите, зачем это нужно? Бывают методы общего назначения, которые срабатывают по ряду триггеров. Например функция по отправке сообщения в аналитику может вызываться сотню раз в секунду, а нам нужно отловить именно ту отправку, которую породит нажатие на кнопку. В этом случае мы можем поставить брейкпоинт на метод нажатия кнопки и добавить команду установки брейкпоинта на произвольной строке программы в произвольном файле. Команда bp s -o -f Calc.swift -l 44 расшифровывается как breakpoint set one-shot на файл Calc.swift на строку 44. Модификатор -o или —one-shot создаст специальный тип брейкпоинта, который «живёт» ровно до момента своего срабатывания, а после исчезает. Таким нехитрым способом мы можем создавать интересные алгоритмы установки брейкпоинтов для отладки нетривиальных багов.

Other breakpoints types

Панель переключения видов левой функциональной колонки Xcode c открытым Breakpoint Navigator и несколькими брейкпоинтами

А есть ли ещё виды брейкпоинтов, о которых мы можем не знать? Конечно, есть. Xcode позволяет добавить некоторые виды брейкпоинтов, которые не относятся к какому-то конкретному файлу и строке. В Xcode есть вкладка Breakpoint Navigator, которая позволяет управлять уже созданными брейкпоинтами сквозь все файлы проекта, а также создавать новые. Внизу окна нашего IDE есть кнопка со значком плюса.

Нижняя функциональная панель левой колонки Xcode при открытом Breakpoint Navigator

Это позволяет использовать 6 дополнительных типов брейкпоинтов:

  1. Swift Exception брейкпоинт — брейкпоинт, останавливающий программу при срабатывании не перехваченного throw для Swift кода.
  2. Exception брейкпоинт — то же самое, но для мира ObjC. Может показаться, что это не актуальный в современном мире брейкпоинт, но это не так. Стоит помнить, что нам пока всё ещё нужен UIKit, написанный на ObjC, ошибки которого мы можем отловить с помощью такого вот брейкпоинта.
  3. Symbolic breakpoint — позволяет останавливать процесс выполнения программы при выполнении кода, ассоциированного с некоторым идентификатором, который Apple называет символом. О символах я расскажу чуть позже.
  4. OpenGL ES Error брейкпоинт — брейкпоинт, останавливающий программу при возникновении ошибки OpenGL при разработке соответствующих приложений.
  5. Constraint Error breakpoint — очевидно, остановит вашу программу при возникновении ошибки автолейаута.
  6. Test Failure breakpoint может вам помочь при отладке тестов.

Так как уместить в этой сессии обзор всех типов точек останова не представляется возможным, я остановлюсь только на самых часто используемых. По своему опыту — я всегда использую Exception breakpoint. Довольно часто при разработке программ я сталкиваюсь с перехваченными системными исключениями, отладить которые порой проблематично из-за крайне неинформативного call stack’а. Думаю, вы сталкивались хоть раз с такой или подобной ошибкой:

Сообщение в Debugger Console при падении приложения из-за не перехваченного исключения ObjectiveC

Exception breakpoint

Для того, чтобы сделать стек вызова более информативным, мы можем добавить Exception breakpoint. Он позволит остановить программу прямо на моменте выброса исключения и отследить цепочку событий, которые привели к такому результату. По умолчанию неперехваченное исключение вызовет аварийную остановку приложения, и в стеке вызова мы ничего полезного не увидим, т.к. исключение будет пробрасываться вверх по стеку вызова и вся информация о месте выброса будет утеряна. Exception breakpoint позволяет остановить программу в момент выброса исключения и уже привычными нами методами получить гораздо больше информации о проблеме, пройдясь по стеку вызова и просмотрев значения переменных, если это необходимо. Я считаю этот тип брейкпоинта очень полезным и использую его на всех проектах по умолчанию. Для этого в Xcode есть удобный механизм, который позволяет указать брейкпоинту уровень и хранить его на трёх уровнях:

  1. Проект.
  2. Воркспейс.
  3. Пользователь.

Просто нажмите на брейкпоинт правой кнопкой мыши и выберите Move breakpoint. Перенесённый на уровень пользователя, брейкпоинт будет доступен на всех проектах, какой бы вы ни открыли в вашем Xcode.

Symbolic Breakpoint

Окно добавления Symbolic Breakpoint

Вторым часто используемым типом брейкпоинтов является Symbolic Breakpoint. Ранее я уже писал, что этот брейкпоинт позволяет останавливать программу при выполнении кода, ассоциированного с каким-то символом, и обещал рассказать подробнее про символы. Так вот, символы — это человекопонятные идентификаторы, которые ассоциируются с тем или иным адресом в памяти. LLDB умеет маппить известные ей символы в адреса функций и наоборот. При каждой сборке проекта система создаёт особый бандл из специальных файлов в формате dSYM, которые расшифровываются как Debug Symbols. Эти файлы хранят что-то вроде таблицы, содержащей в себе некоторые адреса методов и некоторые идентификаторы, среди которых сигнатуры методов, имена файлов, смещения и номера строк. Именно благодаря этим файлам мы можем поставить брейкпоинт на строку файла, получить читаемый стек вызова или расшифровать crashlog приложения из AppStore.

Благодаря этому механизму мы можем поставить брейкпоинт на любом методе класса, зная только его название. При этом нам не нужно достоверно знать, где этот метод объявлен и доступны ли вообще нам исходные файлы. Давайте рассмотрим реальный пример. Вас перевели на новый проект, и первая задача — исправить непонятное поведение на форме ввода данных кредитной карты, когда посреди набора фокус вдруг перепрыгивал на поле ввода имени. Сходу ничего не понятно, кода много, но симптомы ясны. Для расследования необходимо понять, кто и почему инициирует смену фокуса. Можно долго читать код, искать логику в неочевидных расширениях классов, а как надоест — сделать наследника UITextField, переопределив там метод becomeFirstResponder(), поменять реализации и уже там поставить брейкпоинт. А можно за 10 секунд создать символьный брейкпоинт -[UITextField becomeFirstResponder], и программа остановится в момент смены фокуса. По цепочке бэктрейса мы сможем легко восстановить последовательность событий, которые приводят к нежелательным результатам.

У тех, кто пользуется таким видом брейкпоинта в первый раз, наверняка возник вопрос: а что это за символ -[UITextField becomeFirstResponder]? Это ObjectiveC-сигнатура метода установки текста для лейбла. Использование ObjectiveC обусловлено тем, что UIKit написан именно на этом языке. Пара слов для тех, кто имел мало опыта с ObjectiveC. Знак минуса обозначает, что нас интересует инстанс-метод, а не метод класса, далее в квадратных скобках записывается название класса и через пробел метод, двоеточие указывает на то, что этот метод принимает параметр. Тут можно возразить, что пример притянут за уши. Я согласен — в хорошем коде не будет десятка мест с установкой текста лейбла, но моя цель — показать, как это может работать. Давайте рассмотрим более реальный пример. Допустим, для целей отладки нам может понадобиться распечатать последовательность показа вью контроллеров. Добавляем брейкпоинт с символом -[UIViewController viewDidAppear:], указываем дополнительное действие po NSStringFromClass() и, конечно же, не забываем поставить галочку «Automatically continue after evaluating actions».

Мы снова вынуждены использовать ObjC, даже в дополнительной команде, так как находимся в его контексте. Что касается Swift, то символы записываются как название ClassName.methodName(param:). Прописывать параметры не обязательно, LLDB попытается разрешить неоднозначность, если есть методы с одинаковым названием, но разными параметрами.

Рассказывая о символьных брейкпоинтах, я не могу не рассказать о возможности искать символы. Остановив программу любым способом, с помощью брейкпоинта или же просто нажав на пиктограмму паузы, мы можем воспользоваться командой image lookup -r -n и найти интересующие вас символы в вашей программе и во всех загруженных библиотеках. Это действительно делает вас чуть ли не богом дебага, потому как вы властны искать символы везде, скажем в UIKit’e, искать приватные методы, останавливать и изучать внутреннее устройство системных библиотек. Надеюсь, я убедил в вас в силе этого метода и он не раз поможет вам сэкономить время.

Поиск приватного метода в UIKite с помощью image lookup

Watchpoints

Вотчпоинты позволяют останавливать программу, когда изменяется значение переменной. Корректнее будет сказать, что этот механизм позволяет следить за изменениями памяти по заданному адресу с заданным размером, но благодаря LLDB и Xcode разработчику достаточно сделать несколько кликов. Использование вотчпоинтов будет удобным, когда за изменением переменной не следует никакого сайд-эффекта прямо после изменения, но её состояние важно для отложенных вычислений. В ряде случаев может быть непонятно, что инициирует это изменение, и вотчпоинты позволят быстро узнать это. Достаточно приостановить выполнение программы в контексте нужного класса и воспользоваться окном Variables View. Тут будут перечислены переменные в текущем фрейме, доступные к отлаживанию. В крупных проектах вычисление доступных переменных и их типов может занимать некоторое время, поэтому иногда нужно подождать несколько (десятков?) секунд перед тем, как переменные будут доступны к манипуляциям над ними. Приятным бонусом является возможность «заглянуть» внутрь объектов Objective-C: функциональность Variables View позволяет увидеть приватные переменные этих объектов. По клику правой кнопки мыши по переменной нам доступно не так много опций — мы можем изменять значение переменных скалярных типов и, собственно, добавлять вотчпоинты.

Левая колонка DebuggerView, с контекстным меню по одной из переменных

Конечно же, вотчпоинт можно установить и командой LLDB: watchpoint set variable , или, пользуясь функцией сокращения команд LLDB, просто: w s v , но помните, что переменная должна быть видна отладчику, то есть находиться в текущем фрейме. Помимо установки брейкпоинта на изменение переменной, нам доступна установка вотчпоинта на область памяти: watchpoint set expression — 0x0d78ab5ea8. В обоих случаях при изменении содержимого памяти по отслеживаемому адресу произойдет прерывание программы. Установленные точки останова можно посмотреть командой watchpoint list или в Debugger navigator. Так как любые вотчпоинты в итоге следят за адресом памяти, они становятся неактуальны после перезапуска и не сохраняются между перезапусками приложения. Даже если вы установили брейкпоинт на изменение переменной, под капотом механизм lldb вычислил её адрес и поставил вотчпоинт по этому адресу.

Affecting state

Будем закругляться. Последнее, о чем я хотел поведать в рамках этой статьи, — влияние на состояние приложения из LLDB. До этого я говорил только об изменении состояния какого-либо объекта системы при остановке по брейкпоинту. Но что, если нам требуется приостановить программу в произвольный момент времени? Нажатие на значок паузы приводит к приостановке программы, но вот вместо привычного нам кода мы увидим код ассемблера. Так как же добраться до произвольного объекта и выполнить с ним хитрые манипуляции?

Memory graph

Панель инструментов отладчика Xcode с подсвеченной кнопкой Memory Graph

Большинство iOS-разработчиков уже с первых месяцев своей работы используют этот инструмент. Для тех, кто ни разу им не пользовался, поясню. Memory graph позволяет сделать дамп памяти программы и отобразить в виде списка и графа все экземпляры объектов, которые сейчас находятся в памяти. Зачастую этот инструмент используется для выявления утечек объектов и анализа связей, которые привели к такому результату. Но сегодня от этого инструмента нам нужна только возможность остановить программу в произвольное время, найти нужный объект и узнать его адрес. Но что мы можем сделать с этой, казалось бы, бесполезной информацией?

На самом деле — всё, что угодно. Тут нам на помощь приходит мощь ObjC. Мы можем написать [0x7fafffa54a5 setValue:[UIColor redColor] forKey:@»switchedOffColor»] — и мы уже поменяли значение цвета выключенной лампы на красный, используя стандартные методы NSObject, доступные нам из коробки. Но что, если нам недостаточно этих методов, а нужно «дёрнуть» за свои рычаги? Всё просто — мы можем использовать кастинг: [(MyLamp *)0x7fafffa54a5 powerOff]. Используя подобные техники можно воздействовать на любые сервисы, менеджеры и вью модели вашего приложения в любой момент времени. Мы можем сохранить значение этого адреса в переменную для удобства: (MyLamp *)$lamp = 0x7fafffa54a5. Важно, что название переменной должно начинаться со знака доллара. Это переменная будет жить до полной остановки программы, то есть ей можно пользоваться не только в текущем сеансе отладки, но и при следующем прерывании программы в рамках одного запуска. ObjectiveС предоставляет поистине широкие возможности для того, чтобы похакать текущее состояние и обойти многие ограничения, но что делать с классами, доступными только в Swift? Конечно же, при попытке кастинга Swift-класса в ObjC-контексте ничего не произойдёт. К счастью, в Swift есть подобный механизм. Точнее, функция, имя которой — unsafeBitCast. Мы вправе использовать его с адресом: unsafeBitCast(0x7fafffa54a5, to: MySwiftLamp.self) и получить экземпляр класса MySwiftLamp по адресу. Помните, её использование небезопасно, о чём нам намекает её имя, и её крайне осторожно нужно применять в коде приложения. Хотя, когда вам осознанно нужно будет использовать эту функцию, вы будете достаточно опытны для таких предупреждений.

Рейтинг
( 1 оценка, среднее 5 из 5 )
Понравилась статья? Поделиться с друзьями: