Ниндзюцу Xcode

    Если ты много времени проводишь в одном и том же окружении — рано или поздно возникает желание начать как-то экономить свое время и оптимизировать свои действия. В этой статье речь пойдет о некоторых рабочих инструментах и подходах, которые накопились у меня за время программирования под iOS в IDE XCode от очевидных и часто применимых, до редких и довольно тяжеловесных.


    1.Command+Shift+O


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

    На мой взгляд это самый быстрый способ навигации по приложению, потому-что
    • Как видно из скриншота — не требует того, чтобы вы помнили точное название. Ему достаточно, если вы укажите несколько букв из названия в порядке, в котором они идут.Например слово из середины. Или первые две буквы элементов именования
    • Помимо навигации по файлам так же дает навигацию по классам, методам, свойствам класса, структурам.


    2.Сниппеты


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

    Alcatraz


    3.Проект Alcatraz

    Менеджер плагинов для икскода. Встраивается в сам икскод, доступен в меню Window->Package manager

    Плагинов есть целая прорва — от цветовых тем, до довольно значительных проектов, предлагающих live coding, почти как на свифте (правда устанавливать их можно на свой страх и риск, большинство из них не очень хорошо поддерживается, а значит несет определенные риски).
    Очень удобная установка и отключение в 1 клик. В каждом плагине есть ссылка на его сайт или гитхаб, для многих из этого же менеджера доступны картинки или gif-превью.
    Я с помощью менеджера пользуюсь некоторым количеством инструментов, в частности:

    4.Derived data Exterminator



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

    5.FuzzyAutocomplete


    Значительно расширяет autocomplete — он начинает работать примерно, как сочетание Cmd+Shift+O — то есть теперь не обязательно помнить первые буквы каждого метода или класса.
    Люди его воспринимают достаточно по разному — теперь нечасто автокомплит уменьшается до одного варианта и создается впечатление большой кучи информационного мусора, но я без него теперь чувствую себя гораздо хуже.

    6.Полезная мелочевка

    Несколько маленьких, но приятных приспособлений для автокомлпита, таких как
    -QuickLocalization (переводит @«content» в NSLocalizedString(@«content»,@«content»))
    -OMColorSense (в автокомплите показывает цвет, когда заполняешь поля инициализации UIColor)
    -XToDo (дает окошко, в котором можно просматривать в TODO, FIXME и прочие тэги по всему проекту)
    -KSImageNamed (в автокомплите добавляет файлы графических ассетов и отображает их — делая imageNamed: куда более удобным для использования)

    На этом закончим с Alcatraz — каждый имеет возможность выбрать из списка что-то себе по вкусу.

    Interface builder


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

    7.User defined runtime attributes


    Это инструмент для KVC, доступный в IB — позволяет на этапе вызова метода InitWithCoder при инстанцировании объекта задавать значение некоторых свойств. По сути, его действие аналогично вызову метода [self setValue:@«value» forKey:@«key»] при инициализации объекта. Таким образом это позволяет вынести в IB файл достаточно широкий спектр настроек приложения, которыми может заниматься в том числе не-программист.

    8.Инстанцирование объектов



    IB позволяет управлять созданием не только объектов-наследников от элементов UIKit, но и любых произвольных объектов. (С помощью предыдущего пункта как раз можно управлять еще и каким-то свойствами создаваемых объектов) У них, как и у наследников UIKit, будет вызван конструктор initWithCoder: и они точно так же будут уничтожены при выходе контроллера из зоны видимости и стэйка Navigation Controllera, если разработчиком не предусмотрено обратного.
    Я, например, пользуюсь этим инструментом для того, чтобы быстро изменить свойство многих UI элементов, когда UIAppearance и наследование по тем или иным причинам не подходит. Например, когда заказчик пожелал добавить на каждую кнопку в проекте градиент, а на некоторые еще и тени это решилось созданием двух декорирующих классов и развешиванием их в IB.

    9.IBDesignable(XCode 6)


    Подробно можно прочитать вот тут.

    По сути — является удобной оболочкой над User defined runtime attributes — позволяя делать некоторые свойства классов доступными для изменения посредством IB. Это, конечно, еще не дает возможность писать полноценные кастомные UI-компоненты, но неплохо к этому приближает.

    Структура проекта


    10. .pch-файл(XCode 5-, в XCode 6 добавляется вручную)

    В каждом проекте обязательно есть .pch файл (как правило в папке Supporting Files), который представляет собой заголовочный файл, подключаемый к каждому заголовочнику.
    То есть фактически неплохое место для подключения общеиспользуемых на проекте макросов и хидеров (таких как хидеры CoreData или, например Cocos2d для игровых проектов)

    Мультиязычность

    Вообще, XCode это среда не только для Objective-C. И даже не только для Swift. Это большая и взрослая IDE, с помощью которой можно разрабатывать и на других языках

    11.1.Интегрированные языки

    Для меня было приятным откровением, что XCode имеет поддержку языков YACC и LEX из коробки. В проект достаточно добавить .y и .l (или .ym, .lm или .ymm, .lmm в зависимости от тех особенностей, которые вы хотите уметь при компиляции — первые два, например не смогут скомпилироваться с Objective-C кодом, а в последних можно использовать C++-stl)
    У них есть своя секция настроек в проектном файле

    Обратите внимания — что так как эти языки поддерживаются из коробки, то из коробки же генерятся и строки для компиляции, что в какой-то момент послужило неприятным сюрпризом — например XCode долго игнорировал мою попытку развести два генерируемых YACC файла по разным неймспейсом, потому что соответствующая директива перебивалась автоматически заполняемой XCodeом (опция Generated file stem, если кому интересно)


    11.2.Неинтегрированные языки

    Не стоит забывать и о том, что для некоторых задач Objective-C не самый подходящий язык. А расставаться с XCode все так же не хотелось, поэтому вот тут можно найти описание, как прикрутить к XCode, например Perl.
    Если кто-то ищет вдохновения о применении: на перле можно организовать скрипт, который на примере JSON реквеста и респонса генерирует код .h и .m иерархии дата-объектов, под который укладывается эти данные.

    Для многих языков XCode имеет встроенную подсветку.

    Внешние инструменты


    12. Автоматор

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

    Я недавно начал использовать его, но вижу довольно много интересных применений: От простейших многострочных комментариев, до поиска выделенной строчки кода в коммитах гита — и на что хватит фантазии.

    К слову, в Настройках системы (программа Keyboard) можно назначить на созданные сервисы шорткаты и сделать жизнь еще легче.

    13.Synx


    Этот инструмент позволяет привести проект в файловой системе к виду, в котором он присутствует в проекте. Запускается через командную строку. Надежен — операций, в которых он не уверен — он просто не делает, о чем заранее предупреждает.

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

    Отладка


    14. Брейкпоинты.

    Отлаживать приложение приходится всем. И иногда подолгу. И пользоваться этими вещами я начал далеко не сразу. А зря!
    Один из ключевых советов — всегда держать тот или иной Exception Breakpoint включенным. Exception breakpoint срабатывает, когда какое-то исключение срабатывает. В случае, если это исключение необработанное при выключенным брейкпоинте не будет показан стэк, приведший к ошибке. Наверняка все так или иначе сталкивались с проблемой поиска ошибок навроде [array addObject:nil] или out of range. Так вот, такие брейкпоинты — это способ ловить такие проблемы ровно в месте их возникновения.

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

    Если у вас есть есть кусочек крайне сильно используемого в проекте кода (например, CCNode в cocos2d), то без условий отловить конкретную проблему бывает весьма и весьма проблематично. Они поддерживают обычный objective-C синтаксис, то есть там можно проверить, что передаваемый объект конкретного класса, что имеет конкретное значение какого-то свойства и так далее. Очень удобно!
    Ну и да, работа условных брейкпоинтов очень сильно замедляет работу приложения — так что лучше с ними не перебарщивать.

    15. Поколения

    И хотелось бы добавить о поиске утечек памяти в коде. Как правило для этого используется Instruments с пресетом Leaks, но основная проблема этого инструмента в том, что бывают такие утечки, которые этим инструментом за утечки не считаются и мне приходилось встречаться с кодом, где за юзкейс утекает несколько мегабайт, а Leaks не показывает ровным счетом ничего — это связано ровно с тем, что, собственно, считается утечкой. Так что последнее время для поиска существенных проблем с памятью я использую инструмент Allocations.
    Важно. Этот инструмент есть отдельно, но запускать его лучше все-таки в пресете с Leaks — потому что будучи запущенный отдельно он не всегда корректно способен расписать историю Retain/Release для конкретного объекта — не знаю, баг это или фича.
    Так вот. Нажатие кнопки mark generation по сути маркирует каждый созданный к этому моменту не-маркированный объект (в широком смысле — память выделенная под структуры тоже маркируется). Дальше, по мере жизни приложения, в поколении остаются только те объекты, которые к текущему моменту не освобождены.
    Развернув конкретное поколение достаточно несложно найти классы, используемые именно в вашем проекте, а так же посмотреть, почему они до сих пор живы (для каждого объекта можно посмотреть историю — где и когда он получал сообщение retain и где release).

    Прочитать о конкретных аспектах применения этого инструмента рекомендую вот здесь.

    Спасибо за чтение!
    и буду очень признателен каким-то вашим трюкам и наработкам.

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 19

      +1
      Спасибо, большая часть статьи была известна, но кое-что полезное для себя я узнал.
      Как относитесь к AppCode? Я вот перешел на него и с каждым днем радуюсь все больше. Не считая, конечно, IB. Он в AppCode пока что не очень. Но уже определенно быстрее аналога из xCode, такие чудеса :)
        +1
        Мне время от времени о нем напоминают, но пока что не накопилось критической массы хотелок того, чего мне не хватает в XCode) по сути, медлительность IB — это самая большая из претензий, а остальные я даже толком и не вспомню.
        Однако было бы интересно узнать, чем лично Вы пользуетесь более менее регулярно в AppCode из того что проблематично в XCode.
          +1
          Переодически переключаюсь в AppCode для:
          — Search & Replace по всем файлам
          — Поиск неиспользуемого кода
            0
            Отличный рефакторинг, хороший автокомплит, кодогенерация простых вещей вроде decription/encodeWithCoder, неплохие подсказки по коду, ну и в целом за счет множества удобных и настроенных «из коробки» вещей работа становится намного легче и приятней :)
              +1
              Нуу… Автокомплит как раз стал ровно тем, о котором я мечтал с плагином FuzzyAutocomplete, кодогенерация решается собственной, постепенно вырастающей библиотекой сниппетов…

              Но рефакторинг и аналитика качества кода в AppCode, похоже и правда лучше) Спасибо! Плюс один довод таки провести какое-то время за ним.
                0
                да, чуть не забыл. Еще из плюсов работа с git:
                очень классный GUI для всего этого: удобно смотреть диффы, историю коммитов и т.п.
                  0
                  В Xcode GUI для гита тоже весьма неплох. И диффы, и блейм, и история… Всё есть.
                    0
                    Хотя бы на уровне горячих клавиш и простого просмотра списка измененных файлов Xcode уныл, увы :(
                      0
                      Чистая правда) Но, если честно, я не согласен с позицией, что IDE должна быть суперкомбайном, который может вообще все, потому что специализированный гит-клиент и терминал все равно могут лучше. Их и использую)
                        0
                        нене, не подумайте что я говорю о комбайне, но банальное сравнение диффов и коммит с пушем удобней сделать 2 комбинациями клавиш, чем тыкая мышкой, вот и все :)
          0
          Статья добротная, стал «хокаге» по Xcode. Узнал много нового, спасибо.
            0
            А вроде как неспроста не создается вложенных папок? Кажется оно так быстрее читается с файловой системы или еще что то
              +1
              Такое возможно, но
              -на небольших проектах и в эпоху SSD это совершенно точно не имеет значения.
              -на большом проекте я существенных различий в скорости/удобстве работы до и после тоже в общем-то не увидел.
                +1
                IBDesignable

                Ещё IBInspectable для любых классов забыли упомянуть. Xcode 6+.

                В каждом проекте обязательно есть .pch файл

                Xcode 6 его не создаёт автоматом, но можно добавить вручную.

                Это большая и взрослая IDE, с помощью которой можно разрабатывать и на других языках

                Можно, но на практике даже Sublime Text нередко лучше справляется с написанием кода. В Xcode плохо работает выравнивание для не C-подобных языков.

                От себя добавлю очень полезные шорткаты для IB:

                Cmd+Shift+= — подогнать констрейнты под текущий размер вью;
                Cmd+= — подогнать размер вью под её содержимое.

                Ещё очень удобно выучить шорткаты для манипуляции рабочим пространством типа Cmd+Alt+0, Cmd+Enter и тп. И не забывать про Ctrl+1..6 и Cmd+1..8.
                  +2
                  Спасибо за правки про версию XCode — забыл их добавить! За шорткаты для констрейнтов отдельной спасибо)
                  Про выравнивание для не С-подобных языков вы правы, однако есть неплохие плагины для стилей других языков. Надо будет поподробнее посмотреть на Sublime и на настройки такого рода вещей в XCode.
                  –5
                  Лучше просто купить AppCode.
                    +1
                    7.User defined runtime attributes

                    При этом свойства должны быть при объявлении помечены атрибутом IBOutlet в заголовочном файле.


                    Неправда, сколько раз я ставил туда layer.cornerRadius и всё было нормально. Я даже затрудняюсь представить, как в IBOutlet через этот механизм можно что-то записать. Обычно же IBOutlet это UIView. Конечно, можно и сделать IBOutlet из Object типа NSNumber или NSColor и писать туда через этот механизм, но это скорее из области извращения.
                      +1
                      Да, вероятно вы правы — я проверил, действительно IBOutlet модификатор не обязателен и ключ может быть не тривиальным. Исправляю, большое спасибо.
                      0
                      4.Derived data Exterminator

                      А я просто в качестве директории для Derived Data указал /tmp.

                      Only users with full accounts can post comments. Log in, please.