iOs Debug Master

Автор: admin от 17-11-2015, 08:39, посмотрело: 474

Однажды я почти полностью отказался от мышки для навигации по Xcode и вполне этому рад. Следующий шаг — это отказ от визуальных средств управления отладчиком. Зачем? — Увеличиваем возможности, уменьшаем время дебага, тратим меньше калорий для перемещения тяжеленькой ручишки (нам калории нужны, чтобы головой работать) и тем самым провоцируем меньше туннельного синдрома.

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

Не рассматриваю такие темы: как работать в Xcode, как вообще отлаживать приложение, в какой момент нужно это делать и зачем, что такое LLDB, что такое Step Into и Step Over и т.д.

Сразу к примерам:

Настраиваем консоль


Отказываем вот от этой панельки:

iOs Debug Master

Да и вот про эту скоро забудем

iOs Debug Master

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

iOs Debug Master

Спасибо моему коллеге: он осуществил мою давнишнюю мечту — открывать консоль отладчика в новом окне. А то всегда напрягало, что только открыл и настроил вкладки как тебе надо, так сразу же при первом брейкпоинте всё запоролось. Чтобы этого не было идем Xcode -> Behaviours -> Edit behaviours... Далее нам нужна секция Running -> Pause.
Выбираем Show tab named, пишем туда наше уникальное название вкладки, например Debug (замечу, что при повторных запусках вкладка не дублируется), в конце ставим active window — это, как ни странно, открывает новую вкладку (Cmd + T) для нашего отладчика. Ешё я скрыл ненужную правую панель — но это по желанию. Вообще кастомизация среды при разных условиях — это в разделе Behaviours

iOs Debug Master

Всё, мы настроены, двигаем дальше.

Управляем отладчиком


Добавляем сразу в копилку полезных hotkey'ев кто не знал Cmd + Shift + C. Это быстрый переход в консоль.
Сmd + Shift + Y — это скрыть/показать консоль.
Наши новые команды:
Step Intostep или коротко s
Step Overnext или коротко n
Step Outfinish
Continuecontinue или c
Отключить все брейкпоинты — breakpoint disable
За полным списком команд lldb можно отправиться вот сюда
Не буду перечислять все возможности прямых команд LLDB, но их список больше, чем позволяет сделать визуальная среда Xcode и каждый сам вправе решить использовать ему подобный подход или нет и какие команды нужны и интересны. Остановлюсь на том, что показал куда смотреть.
Удобство выполнения команд еще в том, что есть привычный как в терминале переход к предыдущей/последующей команде через стрелки вверх-вниз.
В результате наша работа с отладчиком выглядит вот так:

iOs Debug Master

Swift и obj-c! Что внутри объекта?


Не знаю как вам, но мне не повезло писать проект на Swift с нуля, а пришлось с выходом нового языка в огромном obj-c проекте все новые файлы писать на Swifte. Не пишу про все несостыковки, но основная проблема в отладке, наверное, в следующем:
Создаем простой класс модели на Swift

class TestObject: NSObject {
    var name: String = "name"
    var index: Int = 123
}

Теперь пишем на obj-c простой массив с нашим классом:
NSArray *array = @[[[TestObject alloc] init],
                 [[TestObject alloc] init],
                 [[TestObject alloc] init]];

Теперь ставим брейкпоинт на следующей строчке и смотрим на то, что бы мы увидели в Variables:

iOs Debug Master

Знакомо? А где же наши name и index
Теперь смотрим, что мы можем сами руками в консоле:

(lldb) p array
(__NSArrayI *) $0 = 0x00007f9a1878c6b0 @"3 objects"
(lldb) po array
<__NSArrayI 0x7f9a1878c6b0>(
<CornerApp.TestObject: 0x7f9a1870fc60>,
<CornerApp.TestObject: 0x7f9a1878c650>,
<CornerApp.TestObject: 0x7f9a1878c680>
)

(lldb) po [array debugDescription]
<__NSArrayI 0x7f9a1878c6b0>(
<CornerApp.TestObject: 0x7f9a1870fc60>,
<CornerApp.TestObject: 0x7f9a1878c650>,
<CornerApp.TestObject: 0x7f9a1878c680>
)

(lldb) po array[0]
<CornerApp.TestObject: 0x7f9a1870fc60>

(lldb) po array[0].name
error: property 'name' not found on object of type 'id'
error: 1 errors parsing expression
(lldb) po [array[0] name]
name

(lldb) 

p — это print
po — это print object, кидает объекту сообщение description, обратите внимание, что объектам еще можно послать сообщение debugDescription
po array[0].name — не работат, потому что для отладчика нулевой элемент в массиве типа id. А вот посылка сообщения name (po [array[0] name]) прекрасно работает. Не забываем, про то, что obj-c — это message oriented язык программирования.

Найди меня


Следующий кейс: у нас есть API — мы ходим на сервер за списком стран, потом преобразуем их во внутреннюю логику и где-то храним. Например, наша modelView идет за данными в хранилище и ищет модельку в словаре по ключу:
- (CACountry *)countryByCode:(NSString *)code
{
    return  [_countries objectForKey:code];
}

Что мы видим в Variables? 242 страны, отлично, как нам быстро найти Россию?
iOs Debug Master

Знаю, вот так:
(lldb) po [_countries objectForKey:@"RU"]
<CACountry: 0x7fae00630ba0>

(lldb) po [[[_countries objectForKey:@"RU"] title] string]
Россия

И хочу заметить, что в строке отладчика прекрасно работает автодополнение для посылки сообщений в objective-c

Магические UIView


Наверняка, если делали какой-нибудь нетривиальный UI были ситуации, когда что-нибудь в интерфейсе съехало и нужно разобраться, кто виноват. При это перезапуск приложение грозит тем, что может не удастся воспроизвести ситуацию. Вот тут-то работа с отладчиком незаменима.
В результате выполнения простого
(lldb) po self.view.subviews

увидим что-то вроде такого:
<UICollectionView: 0x7fd9fb81a200; frame = (0 0; 375 667); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fd9fb416cb0>; layer = <CALayer: 0x7fd9fb4067f0>; contentOffset: {0, -180}; contentSize: {375, 843}> collection view layout: <TGLStackedLayout: 0x7fd9fb410000>,
<CASortView: 0x7fd9fb4468c0; frame = (67.5 607; 240 60); clipsToBounds = YES; alpha = 0; opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fd9fb481290,
<UIView: 0x7fd9fb47e240; frame = (0 0; 375 687); alpha = 0; layer = <CALayer: 0x7fd9fb4895a0

Сразу видим набор view, их фреймы, свойства, всё то, что запихнули разработчики Apple в стандартное сообщение description.
Если нужно легко можем уточнить какое-нибудь свойство, можно использовать адрес в памяти напрямую:
(lldb) po [0x7fae2b792ba0 backgroundColor]
UIDeviceWhiteColorSpace 0 1

А вот вам напоследок кусок кода, который может доставать по иерархии все view заданного класса, может покажется полезным. Сам использую.
import UIKit

extension UIView {
    
    func debugAllSubviewsOfClass(cls: AnyClass) -> [String] {
        func goDeepAndPrint(inout views: [String], currentView: UIView) {
            for v in currentView.debugSubview() {
                views.append(v.debugDescriptionWithParent())
                goDeepAndPrint(&views, currentView:v)
            }
        }
        var views = [String]()
        goDeepAndPrint(&views, currentView:self)
        return views
    }
    
    func debugDescriptionWithParent() -> String {
        let parentAddress = self.superview != nil ? String(format: "%p", self.superview!) : "nil"
        return "(self.description), parent = (parentAddress)"
    }
    
    func debugSubview() -> [UIView] {
        return self.subviews
    }
}

extension UITableView {
    
    override func debugSubview() -> [UIView] {
        return self.subviews + self.visibleCells
    }
}

extension UICollectionView {
    
    override func debugSubview() -> [UIView] {
        return self.subviews + self.visibleCells()
    }
}

Summary



  • С отладчиком можно работать не только через кнопочки Xcode.

  • Как настроить открытие консоли при отладке в новой вкладке? Самое начало — большая картинка

  • Быстрый переход в консоль — Cmd + Shift + C,
    свернуть/развернуть консоль — Cmd + Shift + Y

  • Наши новые команды:
    Step Intostep или коротко s
    Step Overnext или коротко n
    Continuecontinue или c
    Отключить все брейкпоинты — breakpoint disable
    Вот тут весь список команд LLDB.

  • Obj-c не видит свойства объекта Swift-ового класса? Не беда:
    (lldb) po [array[0] name]
    

  • В окне variables 242 ключа у словаря?
    Ищем быстро:
    (lldb) po [[[_countries objectForKey:@"RU"] title] string]
    Россия
    

  • Облегчаем себе отладку UIView — чуть выше summary есть немного полезного кода



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

Источник: Хабрахабр

Категория: Веб-разработка / Game Development / iOS

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
  • bowtiesmilelaughingblushsmileyrelaxedsmirk
    heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
    winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
    worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
    expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
    disappointedconfoundedfearfulcold_sweatperseverecrysob
    joyastonishedscreamtired_faceangryragetriumph
    sleepyyummasksunglassesdizzy_faceimpsmiling_imp
    neutral_faceno_mouthinnocent