Подписка на блог

В Телеграме помимо ссылок на заметки делюсь околодизайнерскими наблюдениями.

В Твиттере помимо ссылок на заметки пишу всякую чушь.

В Тумблере и Же-же есть автоматические трансляции. Если не работает, напишите мне: ilyabirman@ilyabirman.ru.

По РСС и Джейсон-фиду трансляции для автоматических читалок

Какао

Что почитать на выходных — 26

Вот что:

  1. Definitive answer to message-eating nil argument. Олег Андреев объясняет, почему клёво, когда отправка сообщений несуществующему объекту (nil) не должна быть ошибкой. Мне всегда нравилось, что в Какао это так.
  2. iPhone: The bet Steve Jobs didn’t decline. Почему заняться Айфоном было очень непростым решением для Эпла.
  3. Giant. Гай Инглиш про Нила Армстронга.
 9   2012   Айфон   Какао   программирование   чтиво   Эпл

Нотация для названий функций

В Какао мне очень нравится, как используется возможность «Объектного Си» вставлять параметры прямо в название методов («селекторов»):

[someObject doStuffWithThing:x andThing:y usingParameter:z];

Получаются нормальные предложения. В большинстве языков так делать нельзя, однако формулировать названия функций так, чтобы параметры продолжали предложение, никто не запрещает. Если параметр всего один, или параметры образуют очевидную последовательность, то это добавит удобочитаемости. Я принял нотацию, согласно которой название функции завершается подчёркиванием, если оно составлено по такому принципу. В этом случае открывающая скобка не отбивается пробелом (вообще, я всегда отбиваю; меня страшно бесит, что в ЦССе так делать нельзя).

Пример перевода:
e2_note_by_id ($id)
e2_note_with_id_($id).

А так могли бы выглядеть некоторые функции с несколькими параметрами:
do_stuff_at_($x, $y),
do_stuff_with_date_($year, $month, $day).

Если параметры не образуют очевидной последовательности или нормально переформулировать смысл функции не удаётся, то функция пишется «по старинке», без подчёркивания в конце:
e2_store_cache ($path, $data, $secure).

А какие вы используете хитрости для повышения удобочитаемости кода?

Какао-наблюдения

С одной стороны, программировать под Мак — в удовольствие: тут нет такой жести, как в Винде, когда какая-нибудь функция возвращает указатели на структуру из 18 указателей, половина из которых указывает на массивы структур других указателей, или когда, наоборот, ссылку на такую структуру нужно передать в качестве одного из 8 параметров какой-нибудь функции, чтобы она в неё же запихала результат (а все остальные параметры сделать NULL, потому, что понять по документации, что они значат, невозможно).

Вот понадобилось мне на днях изменить шрифт в текстовом поле. Код угадал, не глядя в документацию (автозаполнение помогло, конечно); заработало с первого раза:

[textView setFont:[NSFont fontWithName:@«Arial» size:20]];

Что касается setFont:, то я просто предположил, что такой метод может быть, начал писать set..., и выбрал из списка setFont:, у которого единственный параметр — экземпляр класса NSFont. Как сделать нужный NSFont — угадывается по аналогии: очень часто названия конструкторов начинаются с типа создаваемого объекта, например у NSString есть конструктор stringWithContentsOfFile:encoding:error:, который возвращает содержимое файла; у NSArray есть конструктор arrayWithObjects:, который возвращает массив с переданным набором объектов; а у NSColor есть конструктор colorWithCalibratedRed:green:blue:alpha:, который, как нетрудно догадаться, возвращает цвет с заданными R, G, B и непрозрачностью с учётом каких-то цветовых профилей.

С другой стороны, эпловская терминология местами разрывает мозг. Иногда невозможно по три часа найти что-нибудь в документации просто потому, что ты ищешь, например, keyboard layout, а надо искать text input source.

Эмси будущего

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

Во-первых, я сделал шрифт мельче. Когда пунктом меню выступал просто текст в виде NSString, он рисовался стандартным шрифтом для пунктов меню. Я думал, что изменить его я смогу только, если буду использовать кустомный вью (сейчас-то я уже думаю, что, наверное, можно было просто NSAttributedString использовать в качестве тайтла). Короче, теперь у меня используется более мелкий шрифт — из стандартных вещей такой применяется, например, в индикаторе уровня заряда батарейки на ноутбуках.

Эмси будущего

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

Во время паузы вся эта штука красиво зачёрнобеливается.

Кстати, синий градиент — это просто синий прямоугольник высотой в несколько пикселей, которому с помощью Кор-имиджа был сделан вертикальный моушен-блюр ещё на несколько пикселей.

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

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

Эмси

Совершенно поразительно, что все подряд программы-компаньоны к Айтюнсу показывают информацию о играющей песне во всплывающем временном окошке тогда, когда песня только начинается. Это ужасно неудобно:
  • когде песня только началась, тебе, как правило, на неё ещё наплевать;
  • временные окошки обязательно всплывают не там, где тебе нужно, мешая работе;
  • всплытия обычно сопровождаются анимацией, отвлекающей тебя от того, что ты делаешь;
  • они висят на экране слишком долго: ты уже прочитал, а они всё ещё загораживают что-нибудь;
  • они висят на экране слишком мало: ты только начал читать, а они исчезают;
  • в момент, когда тебе нравится песня, и ты задаёшься вопросом о её названии, ответа на этот вопрос нет на экране.
В комплекте с каждым Маком идёт диск с инструментами для разрабоки. Понятное дело, что я их установил практически сразу же, как купил Мак. Я хотел сделать программу, которая бы тихо показывала в правой части меню текущую играющую в Айтюнсе песню. Безо всякого кретинского плавненького скролирования этого названия влево-вправо, как я видел в одной программе. Безо всяких там рейтинговых звёздочек. Тем же самым шрифтом, что и всё остальное. Короче, просто вот так:

Название песни в менюбаре

Тогда я довольно быстро справился с этой задачей: Жан-Даниель Дюпа, автор Спарка (прекрасного менеджера клавиатурных шоткатов) подсказал мне, что нужно копать API под названием Scripting Bridge. Эта штука позволяет используя эплскриптовый словарь любых приложений общаться с ними. Получается вполне поэтический код. Вот так, например, узнаём, что играет в Айтюнсе:

iTunesApplication *iTunes;
iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
if ([iTunes isRunning]) NSString *text = [[iTunes currentTrack] name];


Добиться того, чего я хотел, оказалось не так сложно, но вот только для того, чтобы следить за Айтюнсом, приходилось использовать таймер. Каждые полсекунды я заново спрашивал у бедного Айтюнса, что же в нём играет:

updateTimer = [[NSTimer scheduledTimerWithTimeInterval:(.5)
  target:self selector:@selector(updateSong:) userInfo:nil repeats:YES] retain];


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

notificationCenter = [NSDistributedNotificationCenter defaultCenter];
[notificationCenter addObserver:self
  selector:@selector(updateSong:) name:@"com.apple.iTunes.playerInfo" object:nil];


А ведь такую штуку уже как бы не стыдно показать. Если кто-то хочет попробовать — вперёд, всего 12 килобайт (зип-архив). Называется «Эмси» (Emcee.app). У программы нет меню, иконки в Доке и она отсутствует в списке Force Quit, поэтому чтобы из неё выйти нужно либо открыть Activity Monitor и прибить её там, либо просто сказать терминалу:

killall Emcee

Кстати, картинка сверху — это скриншот.