Добрый день, сегодня вашему вниманию предлагаю вторую часть статьи про отладку приложения в LLDB.
В первой части мы разобрались, как использовать брейкпоинты (breakpoints) в Xcode для изменения существующих свойств переменных и добавления строчки кода через команды-инструкции.
Я создал демо проект намеренно с несколькими ошибками для того, чтобы разобраться, как использовать различные типы брейкпоинтов в LLDB для отладки приложения.
Если вы не изучили первую часть статьи, лучше начните с неё. Давайте я напомню вам важное правило этого туториала: До конца этой статьи вы не останавливаете компилятор и не перезапускаете приложение после самого первого запуска. Вы исправляете ошибки во время исполнения программы.
Точки наблюдения (Watchpoints)
Итак, следующая ошибка в приложении:
3. Можно подгрузить посты более 7 раз.
Как воспроизвести ошибку:
Как один из вариантов выявления ошибки, нужно выяснить, как обновляется integer переменная pageNumber после того как новые посты загружаются на страницу. Так как вы все ещё мало знакомы с моим кодом, то чтобы понять что в нём происходит, придется потратить какое-то время.
Не стоит волноваться. Применим немного магии.
Из первой части статьи мы узнали, что GET HTTP запрос выполняется в секции pragma mark Networking. В ней содержится ровно одна функция loadPosts. Поместите брейкпоинт на первую линию этой функции и потяните таблицу вниз для обновления. Компилятор остановится на этом брейкпоинте.
Objective-C
Swift
В нижнем окне отладчика нажмите на кнопку «Показать переменные». Слева выдвинется новое окошко, в котором вы увидите все переменные PostsTableViewController.
Направьте курсор на переменную pageNumber, кликните правой кнопкой мыши и выберите “Watch _pageNumber” / “Watch pageNumber” для Objective-C и Swift соответственно.
Objective-C
Swift
Таким образом вы создали так называемую точку наблюдения (watchpoint) для переменной pageNumber. Watchpoint – это тип брейкпоинта, который останавливает отладчик каждый раз когда значение переменной, на которую он установлен, меняется.
Objective-C
Swift
Продолжите выполнение программы. Отладчик остановится и вы увидите примерно следующее:
Objective-C
Если вы обратитесь к пункту 1 в отслеживании стека, то он приведет вас к следующему фрагменту кода:
Swift
Логично заключить, что каждый раз после удачного HTTP GET запроса, переменная pageNumber увеличивается на 1 до тех пор, пока переменная state (типа enum) в состоянии “active”. Эта переменная может иметь 2 состояния: либо активна (“active”), либо неактивна (“inactive”). Состояние “active” предполагает, что пользователь может подгружать посты (то есть лимит в 7 загрузок не достигнут). Состояние “inactive” наоборот, предполагает, что больше пользователь не сможет подгрузить посты. В итоге, нам нужно добавить логики в функцию updateForNetworkCallEnd, которая бы проверяла переменную pageNumber и выставляла бы переменной state соответствующее состояние.
Как вы уже догадались, гораздо легче сначала проверить гипотезу не останавливая компилятор, прежде чем делать изменения в коде.
Отмечу, что в секции pragma mark Support уже есть нужная нам функция (setToInactiveState), которая устанавливает переменной state состояние «inactive».
Добавьте брейкпоинт на одну линию выше условия if. Так же добавьте следующую команду-инструкцию в отладчик.
Objective-C
Swift
После этого удалите самый первый брейкпоинт, который вы использовали для того, чтобы установить точку наблюдения. Так же деактивируйте и сам watchpoint.
Objective-C
Objective-C
Swift
Swift
Теперь пролистайте вверх таблицы, потяните вниз для обновления и начинайте листать.
Все получилось! Но пока рано праздновать, у нас все еще остался один баг для исправления!
Что дальше?
Финальная, третья часть статьи, в которой мы узнаем еще об одном типе брейкпоинтов — символьном (symbolic breakpoints).
В первой части мы разобрались, как использовать брейкпоинты (breakpoints) в Xcode для изменения существующих свойств переменных и добавления строчки кода через команды-инструкции.
Я создал демо проект намеренно с несколькими ошибками для того, чтобы разобраться, как использовать различные типы брейкпоинтов в LLDB для отладки приложения.
Если вы не изучили первую часть статьи, лучше начните с неё. Давайте я напомню вам важное правило этого туториала: До конца этой статьи вы не останавливаете компилятор и не перезапускаете приложение после самого первого запуска. Вы исправляете ошибки во время исполнения программы.
Точки наблюдения (Watchpoints)
Итак, следующая ошибка в приложении:
3. Можно подгрузить посты более 7 раз.
Как воспроизвести ошибку:
- Включите интернет на вашем айфоне/симуляторе
- Пролистайте вниз до конца таблицы, чтобы подгрузить больше постов.
- Вы сможете подгрузить посты более 7 раз (Хотя в данном приложении у пользователя не должно быть такой возможности).
Как один из вариантов выявления ошибки, нужно выяснить, как обновляется integer переменная pageNumber после того как новые посты загружаются на страницу. Так как вы все ещё мало знакомы с моим кодом, то чтобы понять что в нём происходит, придется потратить какое-то время.
Не стоит волноваться. Применим немного магии.
Из первой части статьи мы узнали, что GET HTTP запрос выполняется в секции pragma mark Networking. В ней содержится ровно одна функция loadPosts. Поместите брейкпоинт на первую линию этой функции и потяните таблицу вниз для обновления. Компилятор остановится на этом брейкпоинте.
Objective-C
Swift
В нижнем окне отладчика нажмите на кнопку «Показать переменные». Слева выдвинется новое окошко, в котором вы увидите все переменные PostsTableViewController.
Направьте курсор на переменную pageNumber, кликните правой кнопкой мыши и выберите “Watch _pageNumber” / “Watch pageNumber” для Objective-C и Swift соответственно.
Objective-C
Swift
Таким образом вы создали так называемую точку наблюдения (watchpoint) для переменной pageNumber. Watchpoint – это тип брейкпоинта, который останавливает отладчик каждый раз когда значение переменной, на которую он установлен, меняется.
Objective-C
Swift
Продолжите выполнение программы. Отладчик остановится и вы увидите примерно следующее:
Objective-C
- Записи старых и новых значений переменной pageNumber.
- Отслеживание стека кода, который изменяет значение переменной pageNumber.
- Текущая точка, которая вызвала изменение переменной pageNumber – setter метод этой переменной.
Если вы обратитесь к пункту 1 в отслеживании стека, то он приведет вас к следующему фрагменту кода:
Swift
- Отладчик информирует вас о том, что точка наблюдения, которую вы поставили, что-то выявила.
- Отслеживание стека кода, который изменяет значение переменной pageNumber.
- Текущая точка, которая вызвала изменение переменной pageNumber – функция updateForNetworkCallEnd.
Логично заключить, что каждый раз после удачного HTTP GET запроса, переменная pageNumber увеличивается на 1 до тех пор, пока переменная state (типа enum) в состоянии “active”. Эта переменная может иметь 2 состояния: либо активна (“active”), либо неактивна (“inactive”). Состояние “active” предполагает, что пользователь может подгружать посты (то есть лимит в 7 загрузок не достигнут). Состояние “inactive” наоборот, предполагает, что больше пользователь не сможет подгрузить посты. В итоге, нам нужно добавить логики в функцию updateForNetworkCallEnd, которая бы проверяла переменную pageNumber и выставляла бы переменной state соответствующее состояние.
Как вы уже догадались, гораздо легче сначала проверить гипотезу не останавливая компилятор, прежде чем делать изменения в коде.
Отмечу, что в секции pragma mark Support уже есть нужная нам функция (setToInactiveState), которая устанавливает переменной state состояние «inactive».
Добавьте брейкпоинт на одну линию выше условия if. Так же добавьте следующую команду-инструкцию в отладчик.
Objective-C
expression if (self.pageNumber >= 7) {[self setToInactiveState]}
Swift
expression if (self.pageNumber >= 7) {setToInactiveState()}
После этого удалите самый первый брейкпоинт, который вы использовали для того, чтобы установить точку наблюдения. Так же деактивируйте и сам watchpoint.
Objective-C
Objective-C
Swift
Swift
Теперь пролистайте вверх таблицы, потяните вниз для обновления и начинайте листать.
Все получилось! Но пока рано праздновать, у нас все еще остался один баг для исправления!
Что дальше?
Финальная, третья часть статьи, в которой мы узнаем еще об одном типе брейкпоинтов — символьном (symbolic breakpoints).