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

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

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

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

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

Какао

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

Вот что:

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

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