Оптимизация ПО для iPhone: живой пример

    Программирование на платформе iOS (той, что еще недавно называлась iPhone OS) – странное сочетание радости от плодотворной работы и муки плавания против течения. У каждого разработчика свое мнение относительно того, какая из этих компонент преобладает. Лично мне это занятие нравится, поэтому мне показалось уместным поделиться впечатлениями от процесса работы над очередным проектом.

    В конце марта мне предложили написать мобильную версию Bookmate для iPhone. Дизайн большей части приложения был уже готов в виде толстенного PSD, на стороне сервера работа кипела, мне же оставалось, как говорится, «всего лишь» написать клиентскую часть на Objective-C.

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

    Архитектура


    В двух словах, Bookmate – это сервер, на котором хранятся книги, состоящие из набора HTML-файлов. Основная задача клиента Bookmate (в простонародии, «читалки») – показывать и обрабатывать этот HTML. Почему HTML? В отличие от, например, PDF, его достаточно легко переформатировать при изменении размера шрифта, что совершенно необходимо в мобильном приложении на крошечном экране. С другой стороны, поскольку в HTML отсутствует привычное понятие страницы, он, строго говоря, не очень подходит для отображения книг в традиционном постраничном виде. Чтобы правильно перенести строку, которая не умещается на экране, на следующую страницу, нужно знать ее вертикальный отступ на странице. Для этого движок HTML должен сначала обработать весь документ и просчитать размеры и координаты всех блоков в документе согласно таблице стилей. После этого можно делать то, что делает любая программа верстки типа Adobe InDesign или QuarkXPress.

    Коллеги из Bookmate к тому моменту уже написали библиотеку на JavaScript, которая все это делает красиво и быстро.

    Hello iPhone


    В качестве базовой тестовой платформы мы выбрали iPhone 3G, т.к. это и очень популярная в России, и самая старая модель iPhone, у меня сохранившаяся. В качестве одной из тестовых книг выступило издание «Модели для сборки» Хулио Кортасара в одном файле размером 890 КБ.

    Первый прототип представлял из себя UIWebView, библиотеку JavaScript и некоторое (хотя и существенное) количество кода прослойки между ними на Objective-C.

    iPhone 3G – весьма и весьма шустрый телефон. Местами. Честно говоря, я вряд ли когда-либо пытался открывать в Mobile Safari настолько тяжелые сайты, да я и не уверен, что такие встречаются в природе. Бедный айфон! За те 40 с лишним секунд, которые у него уходили на открытие «Модели для сборки», он успевал и закрыть все остальные приложения из-за нехватки памяти, и орать мне о том, что сейчас память кончится вообще, и стонать о тяжелой судьбе, и греться не в силах что-либо изменить.

    Но нам в тот момент было не до шуток. Первый зерг из авангарда вцепился в ногу, а земля дрожала под полчищем, еще невидимым, но уже страшным.

    Оптимизировать, по сути, было нечего. Добрую половину этих 40 секунд WebKit занимался парсингом, построением DOM, пересчетом геометрии и пожиранием (за неимением других терминов) памяти. Последнее само по себе является серьезной проблемой в iOS из-за невозможности использовать диск для виртуальной памяти, а в нашем случае это еще приводило к необходимости срочно освободить память за счет фоновых программ (таких как Mail и Phone), что также занимает время. JavaScript, перебирающий весь DOM, просто добивал WebKit.

    Такая производительность, очевидно, никого не устраивала. Очевидно было и то, что JavaScript на айфоне недостаточно быстр для наших целей, и то, что мы не можем позволить себе 20 МБ памяти.

    И что с этим делать?


    Чтобы лучше понять масштаб катастрофы, нужно немного прерваться на описание контекста, в котором она происходит. WebKit – библиотека с открытым кодом. Но в iOS она относится к private API, использование которых запрещено Эпплом. Даже если бы было возможно собрать WebKit для iOS самому и включить его в программу в виде статической библиотеки, UIKit уже линкуется с WebKit, что неизбежно приводит к коллизиям символов; даже если переименовать весь WebKit и избежать коллизий, UIWebView не предоставляет никакого доступа к компонентам WebKit, на которых он построен: см. выше про использование private API. Выходит, что мы не можем добраться до DOM из Objective-C напрямую, без JavaScript. А значит, как сказала еще недавно одноглазая черепаха слепой, «Ну все, приплыли».

    Остается только одно – забыть про WebKit: парсить HTML с помощью libxml и рисовать DOM вручную. То есть нужно написать свой движок HTML. На такое я мог согласиться только ради эксперимента, чтобы понять, имеет ли это смысл с точки зрения производительности. В конце концов, я видел исходники WebKit и отдаю себе отчет в бесперспективности попытки переписать его в одиночку, при этом сделав его намного быстрее. С другой стороны, мы не используем возможности WebKit даже на 10%. Если писать свой узкоспециализированный движок, он будет в десятки раз легче любого современного браузера. Эх, где наша не пропадала!

    libXML


    На ежегодно проводимом в аду для программистов конкурсе на худшие API у libxml опять главный приз. Возможно, я придираюсь, но исходники намного понятнее документации. Типичный пример:
    Function: htmlCtxtReset
    void htmlCtxtReset(htmlParserCtxtPtr ctxt)
    Reset a parser context
    ctxt: an HTML parser context

    На полном серьезе, и это все?! Все, что тут написано, и так понятно из названий функции и аргумента. Что именно эта функция делает? Зачем она нужна? В каких случаях ее использовать? Какой, извините, балбес это написал? Садись, libxml, двойка.

    Справедливости ради стоит сказать, что сама библиотека работает достаточно хорошо, чтобы ей пользовались почти все. И в жизни она намного проще. И есть на каждом айфоне.

    Первые результаты


    Чтобы потерять как можно меньше времени на тупиковую разработку, я начал с самого медленного участка. Это вычисление размеров блоков текста, сводящееся к суммированию размеров глифов. Результаты замеров производительности оказались не без сюрпризов.
    • UIWebView+JavaScript – 38 секунд, 20 МБ памяти. Это наш первый вариант после всех оптимизаций.
    • NSString, -sizeWithFont: – 14 секунд, 8 МБ памяти. Поскольку нет смысла многократно вычислять размер одних и тех же глифов в одном шрифте, результаты кэшируются. 35% времени занимает вызов метода -[NSString sizeWithFont:].
    • Core Text под iPhone OS 3.1.3 – более 70 секунд. Core Text является private API в iPhone OS до версии 3.2, мне просто хотелось сравнить его скорость, т.к. это изумительно простой в использовании и очень быстрый на маке инструмент.

    Вооружившись цифрами, я написал письмо в тех. поддержку для разработчиков (т.н. DTS, Developer Technical Support, являющаяся в целом платной услугой). Заодно спросил, почему функция CGFontGetGlyphsForUnichars(), лежащая в основе -[NSString sizeWithFont:], относится к private API.

    Вот за что я уважаю Apple, так это за отношение к разработчикам, когда последние не ноют на весь интернет, а задают вопросы «по установленной форме». Через два дня я получил развернутый ответ на мои вопросы, из которого следовало:
    • доступ к WebKit не предусмотрен политикой партии;
    • Core Text под iPhone OS до версии 3.2 является private API из-за того, что слишком медленный; начиная с версии 3.2, он должен быть существенно быстрее UIWebView+JavaScript;
    • CGFontGetGlyphsForUnichars() является private API по причине ее не вполне адекватного дизайна; в интернете можно найти ее аналоги и убедиться, что это так и есть;
    • в целом я на правильном пути, ибо другого они сами не знают;
    • придется сделать выбор между удобством -[NSString sizeWithFont:] и скоростью Core Graphics.


    За дело!


    Алгоритм выкладки текста звучит довольно просто, если не вдаваться в детали. Сначала нужно разбить текст на фрагменты с одинаковым стилем, например, если в середине блока текста встречается фраза, выделенная курсивом, такой блок разбивается на три стилевых фрагмента. Затем нужно понять, в каких местах текст можно переносить на новую строку – это, как правило, знаки препинания между словами или переносы внутри слов. Назовем их кандидатами на перенос. Затем мы берем фрагменты текста между кандидатами на перенос, один за другим, считаем их длину, и ставим их на строку до тех пор, пока их суммарная длина не превысит длину строки. Аналогично со страницами: добавляем строки до тех пор, пока очередная строка не вылезет за высоту страницы.

    Получается внушительный набор объектов: каждый блок текста (например, параграф) состоит из массива строк, содержащих т.н. glyph runs – фрагменты текста одного стиля. Эти самые glyph runs мы и рисуем целиком как они есть.

    В этот момент появляются интересные возможности для оптимизации, а код быстро превращается в спагетти. По мере того, как мы опускаемся к самым низкоуровневым API, становится понятно, что лингвистического образования не хватает. На горизонте возникают все новые системы письменности, с которыми этот код не работает. Например, из-за направления письма, как в арабском или иврите, или из-за отсутствия пробелов между словами, как в тайском.

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

    Тем не менее, по части производительности удалось добиться значительного прогресса по сравнению с тем, с чего мы начали. Сейчас шедевр Кортасара появляется на экране менее чем за 6(!) секунд. Это был по-настоящему тяжелый месяц. Мне пришлось временно перепрошить себе мозг, иначе он наотрез отказывался работать с HTML и CSS. Моя жена все это время слушала из моего угла только кряхтение да матюки. Клиенту было тоже не сладко: во-первых, никто не рассчитывал на лишний месяц, во-вторых, начало работы над проектом обескураживало («хорошенький старт, что ж дальше-то будет?»), в-третьих, не было никаких гарантий, что эта куча фанеры вообще сможет взлететь. Однако, кто не рискует, тот ходит пешком. А нам так хотелось в небо!

    Приложение Bookmate уже доступно в App Store (ссылка открывается в iTunes; если она по какой-то причине не работает, есть альтернативная, открывается в браузере).

    Эпилог


    Про Стива Джобса рассказывают такую историю. В 1983 году он убеждал инженеров оптимизировать время загрузки макинтоша такими словами: «Сколько людей будет пользоваться макинтошем? Миллион? Нет, больше. Бьюсь об заклад, через несколько лет пять миллионов людей будут включать свои макинтоши хотя бы раз в день. Допустим, вы можете сократить время загрузки на 10 секунд. Умножьте это на пять миллионов пользователей, получится 50 миллионов секунд, каждый божий день. За год это, наверное, десятки жизней. Если вы сделаете его загрузку на 10 секунд быстрее, вы спасли десяток жизней. Ну что, оно того стоит?». Думаю, да.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 83

      +3
      Bookmate понравился. Кто авторы? Кто делал дизайн? И как попасть туда?

      Ваша история — выше всяких похвал, спасибо!
        0
        Спасибо.

        Все копирайты принадлежат компании Bookmate (если Вы это имели в виду, спрашивая об авторах). Дизайн программы они разрабатывали сами.

        «И как попасть туда?»
        Вы имеете в виду в Bookmate? Просто зарегистрироваться либо на сайте, либо в приложении. Процедура очень простая, главное – чтобы ник не оказался занят.
          0
          Нет, под авторами я имел ввиду кто является создателем? Веб студия или это стартап?
          Зарегистрироваться не могу — говорит, что надо подождать до сентября или получить инвайт.

          кстати — один вопрос — как вы получали метрики по использованию памяти?
            0
            Стартап. Они, вроде бы, уже далеко не первый день существуют, но, поскольку их основной продукт – одноименный веб-сервис – еще не открылся полностью, букмейт можно считать стартапом.

            В комплекте с Xcode есть программа Instruments, в ней есть инструмент Activity Monitor, который показывает кол-во памяти в колонке Real Mem.
          0
          Инвайты раздают в группе Bookmate на ВКонтакте vkontakte.ru/club19037757
            0
            меня нет на вконтакте (вообще нигде нет) :) можно ли как то более простым способом?
        +5
        За ссылку на Bookmate вам БОЛЬШОЕ спасибо уже от 6 человек ;-)
        Одна девочка попросила даже расцеловать, но я воздержусь, извините :)
          0
          в русском AppStore не нашел bookmate, и на сайте регистрация закрыта
            0
            Попробуйте itunes.apple.com/ru/app/id386177450?mt=8
            Почему-то правильная ссылка, в виде itunes.com/apps/, пока не работает. Очевидно, у админов iTunes Store сегодня выходной.
              0
              в браузере-то я увидел приложение, а вот с телефона в AppStore не вижу. itunes под рукой нет к сожалению.
                +1
                Поиск в AppStore пока(!) не дает результата. К сожалению. Но, если зайти в категорию «Books», выбрать кнопку «Free App» то приложение будет одно из 25 первых.
                Скачал так.

                Спасибо, давно искал именно это. Скачал несколько книг, уже читаю. Все книги, что хотел прочитать, уже есть в базе. Появится возможность их покупать, буду покупать. До этого покупал на litres.ru, но с покупкой iPhone перестал, так как лень загонять их на телефон. А тут прямо все само собой решилось! ;)

                Немного не хватает наличия разделов. Не всегда знаешь название, а интересует конкретное направление (фантастика, деловая литература и т.д.).
            +1
            Тоесть вы пытались по сути в своём приложении распарсить другое приложение. Потому как сайты(html, css, js) не что иное как настоящии программы и мы их каждодневно скачиваем.

            Изначально архитектура была не правильной, сайт должен был сделать api, той же мега библиотекой на javascript что у них у же была, отдавать книгу хотя бы в xml.

            А как книги хранятся на сервере?
            И как без api вы сделали регистрацию на клиенте? Парсите сайт?

            Кстати objective-c тот что для iphone не поддерживает soap.
            Andriod тоже, ну тут больше политика партии(гугл) у них есть свой GData и они больше rest ориентированы.

              0
              soap — на плаху, и забудьте о soap как о страшном сне — фикция и фуфел этот soap
                –3
                Не вижу аргументов
                Microsoft, Oracle, IBM и многие другие компании строят на нём свой бизнес ну или часть бизнеса:)
                  +3
                  я активно использовал и использую soap — и аргументы то как раз вижу. начиная от мега fail в Microsoft WCF с SOAP'ом, где svcutils генерирует по wsdl'ке java сервера просто непонятно что, при чем не компилирующиейся вообще никак, заканчивая что Microsoft движется симимильными шагами в сторону REST, чего стоит OData, которая внедряется в последние продукты от них.

                  Oracle, IBM не особо показательны, ибо монстры и turnaround занимает дичайшее время.
                    –2
                    Rest вы можете сделать и без soap например asp.net mvc отдавать json/xml да что хотите, в wcf4 сервисы могут быть как soap так и rest.
                    Приходите в браузер или делайте запрос по url и получаете json/xml/

                    Про какой fail вы говорите, microsoft генерирует корректный wsdl
                      +3
                      Microsoft то генерирует корректный wsdl, который потом можно использовать с помощью генератора от того же Microsoft.

                      Все веселее становится, когда речь заходит о wsdl, не сгенерированный тулзами от Microsoft — который абсолютно валиден, но Microsoft поддерживает только определенный subset (как в случае WCF), или просто вы попадаете на баги svcutils (попробуйте скормить два wsdl с одинаковыми классами) — вот тогда и начинается свистопляска. wsdl.exe — тот еще багоделатель то же.
                0
                Нет-нет, я, наверное, неправильно выразился. На сайте есть API, через которые и работает программа. По сути, теми же API пользуется и он-лайн читалка. Регистрация происходит тоже через API. Парсить сайты – полное безумие, согласен. Я имел в виду парсинг самих книг, полученных с сервера через API. Сами книги – в HTML.

                Re: «Кстати objective-c тот что для iphone не поддерживает soap». У эппла нет SOAP API, но кто мешает написать это самому? JSON у них тоже нет, но мы им активно пользуемся. Главное – у эппла есть полный набор сетевых библиотек, на все вкусы: NS* на Objective-C, CFNetwork на C, и даже BSD sockets, если нужно что-то совсем из ряда вон.
                  0
                  Написать то можно, но это же стандарт, которые apple так поддерживает — www.w3.org/TR/soap/ в настольной версии, тоесть если писать под MacOSX там такая библиотека из коробки на сколько знаю… Хочется из коробки.

                  В андроиде google могли бы перенести из java soap, но они поддерживают только java.net.HttpURLConnection что даёт нам только rest запросы. Как раз чтоб работать с Google сервисами
                    0
                    зачем вообще этот soap из коробки? чем rest не устраивает — передавайте данные как хотите, хоть в plain text — тем более, что soap сообщения просто монстрообразны и их парсинг все же не так легковесен на телефонах, как на больших машинах.
                      +1
                      Так в том то и дело, что в отличие от rest парсить ничего не надо, если на другом конце есть поддержка соап.
                      Вообщем хватит флудить, топик не про rest vs soap
                        0
                        ууу, это если вы microsoft -> microsoft или weblogic -> weblogic используете. а как что не так — soap резко оказывается не совсем стандартным, во всяком случае, генераторы от microsoft закидывают лапки и просятся домой — а самому писать код, да еще в вермешели от microsoft это удовольствие гораздо меньшее, чем распарсить xml с rest сервиса, а если есть xsd — то тот же microsoft сильно не брыкается.

                        но вы правы — топик не о том.
                  0
                  WSDL2ObjC генерирует ObjectiveC проски по заданному WSDL. Сам использовал его для доступа к очень обширному API.
                  Только собирать его нужно из исходников. Бинарник, выложенный на сайте, устарел и содержит кучу ошибок.
                    0
                      0
                      Да, есть сторонии библиотеки, где то даже подборку видел, жаль что из коробки apple не хочет поддерживать.
                    +4
                    Полезная статья. Особенно для тех, кто пойдет вашим путем.

                    Я так понял, с технологией у вас выбора не было?
                    Неужели все так сложно во всех читалках? Их же пруд пруди. Есть платные, бесплатные подо все мыслимые и немыслимые форматы. Почему именно такой путь вы выбрали? Это ж чтобы читать книгу надо быть подключенным к сети или сначала она закачивается на устройство?

                    Все-таки немного непонятна политика: книги на сайт загружаются в формате epub и fb2… А потом преобразуются в html, а потом разработчик изобретает велосипед, на котором давно «ездят» читалки этих очень распространенных форматов. Я правильно понял механизм? В чем преимущество для пользователя? Ваш формат удобнее, нежели fb2 и epub? Я не критикую, мне просто интересно.

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

                    Да, про XML еще подумайте тоже.
                      +1
                      Присоединяюсь в вопросу об fb2. Есть открытый fbreader, который прекрасно работает даже на тяжёлых книжках с картинками. Изобретение велосипеда вообще не понятно.
                        0
                        Насколько я понимаю (поправьте меня, если я неправ), fbreader делает примерно то же самое, что и мы, за одним маленьким исключением: он не умеет разбивать текст на страницы, как в бумажных книгах. В этом-то вся загвоздка. Чтобы просто показать HTML в окне с прокруткой, не нужно ничего, даже Javascript. UIWebView с этой задачей справляется легко, хоть и не так быстро.
                        +1
                        Про выбор формата Вам, наверное, лучше ответят в Bookmate. Насколько я понимаю, они достаточно серьезно препарируют исходники в том же fb2 при импорте/закачке книги. Насколько это необходимо, не берусь сказать.

                        Собственно, вся проблема с изобретением велосипеда связана исключительно с желанием показать книгу постранично, как будто она на бумаге. Та же Станза, например, делает то же самое, отличия только в реализации. Если бы мы решили ограничиться окном с прокруткой, велосипед не то чтобы не пришлось изобретать – он был бы не нужен вовсе. Загрузил HTML в UIWebView одной строчкой кода, и готово. Но Букмейт провел свое собственное исследование рынка, из которого следовало, что нужно непременно сделать возможность перелистывания страниц, как в бумажных книгах.

                        О расчетах на сервере мы действительно думали, но в итоге пришли к мнению, что это слишком сложно. Фишка в том, что кроме выбора шрифта и его размера у нас есть еще одна переменная: ориентация аппарата. Она тоже влияет на количество текста, умещающееся на странице. Таким образом, число вариантов сразу умножаем на 2. Кроме того, Эппл изредка обновляет шрифты в системе и у них меняется метрика. Следить за такими вещами, если честно, просто не хочется. Да, мы потратили некоторое время на реализацию движка, но он достаточно универсален, поэтому нам не придется что-то постоянно переделывать ради поддержки его работоспособности. Чтобы улучшить – другое дело.

                        Насчет XML надо спросить – я могу не быть в курсе всего комплекса причин, по которым это работает именно так, как сейчас.
                        0
                        честно говоря не понял подход грузить книгу целиком в память.
                        почему не сохранить в CoreData, для отображения грузить только кусочек необходимый для текущей страницы, а подготовку удобного формата при необходимости переложить на сервер?
                          0
                          Большинство книг действительно разбиты на части вменяемых размеров и там таких проблем нет. В силу неизвестных мне обстоятельств (скорее всего, оригинальный fb2 был корявый) «Модель для сборки» оказалась монолитным куском. Там даже оглавления-то нет.

                          Идея была в том, чтобы тестировать приложение на экстремальном материале. Иначе шум в бенчмарках очень большой. Кроме того, если мы смогли найти одну такую корявую книгу, она не последняя. А пользователю неизвестно что у нее там не так, поэтому программа должна «просто работать», независимо от того что ей подсунули в качестве рабочего материала.
                            0
                            ну так один монолитный кусок это хорошо) его можно сохранить и выбирать кусочки нужным размером в зависимости шрифта на странице, а книги из нескольких html склеить в один.
                            Насколько я понял проблема была только в рендере всего и сразу.
                          0
                          Получается bookmate конкурент imobilco? Или не планируете делать магазин электронных книг?
                            0
                            Это ваше первое приложение? Клиент вы делали в одиночку? Сколько времени ушло, какова компенсация, если не секрет?
                              +2
                              «Это ваше первое приложение?»
                              4-е в App Store.

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

                              «Сколько времени ушло»
                              4 месяца, плюс-минус выходные.

                              «какова компенсация, если не секрет?»
                              Извините, секрет.
                              +1
                              Кстати, а почему нельзя делать расчёты глифов заранее и хранить на сервере? Как минимум для одних устройств набор шрифта одинаков.
                                0
                                Потому что считать их на лету на несколько порядков быстрее, чем сделать запрос на сервер. И, конечно, гибче, потому что при обновлении/добавлении шрифтов на сервере ничего делать не нужно.
                                +1
                                Насчет движка сафари Safari, стоит прочитать про создании читалки Аймобилко.

                                habrahabr.ru/company/imobilco/blog/95249/
                                  0
                                  К сожалению движок Аймобилки работает на столько медленно, на сколько описано в этой статье. Это очень неприемлемо.
                                    0
                                    Работает он приемлемо.
                                    Нативный клиент конечно будет быстрее, зато теряется кроссплатформенность.
                                      +1
                                      Зато у вас выделения текста нету :)

                                      Мы, кстати, по этой причине и начали делать на веб-технологиях, а также потому, что в дальнейшем наши книги не будут ограничиваться только текстом, но и видео, аудио, интерактив, сложное форматирование. В вебките это есть «из коробки». А по производительности нам ещё есть куда расти.
                                        0
                                        С выделением все решается без проблем. С интерактивными штуками тоже не вижу особых проблем.
                                        А вот сложное форматирование конечно да, вебкитом удобнее :) поэтому мы тоже рассматривали вариант использования вебкита изначально.
                                          0
                                          С выделением все решается без проблем.

                                          Может, я какую глупость скажу (не айфон разработчик я), но проблемы всё-таки есть. Насколько я понимаю, вы отрисовываете текст в картинку, поэтому всё так быстро. Для добавления полноценного текста (который можно выделять) нужно использовать другой компонент, который будет работать на порядок медленнее. Поэтому во всяких станзах и шортбуках выделение текста не нативное.

                                          С интерактивными штуками тоже не вижу особых проблем.

                                          Так как ePub — по сути zip-архив с кучей xhtml файлов, мы можем без проблем вставить в книгу произвольный Javascript. Как вы хотите делать интерактив через ObjC?
                                            +1
                                            Выделение и копирование текста будет, не переживайте :) По поводу отрисовывания текста в картинку, я, честно говоря, не понял. Видеокарта может показывать только двухмерные битмапы, поэтому любые шрифты в какой-то момент обязательно растеризуются. У нас они растеризуются так же, как и в UIWebView. Более того, для отрисовки глифов мы используем ту же функцию из Core Graphics, что и UIWebView. А нативное выделение текста или нет, не имеет принципиального значения. Хотя очень приятно, если оно вам досталось «for free».

                                            По поводу интерактива: нет ничего, что можно сделать на JS и нельзя на ObjC. Серьезно. Если, опять-таки, поддержка аудио/видео вам досталась бесплатно из WebKit — это хорошо, меньше времени на разработку.
                                              0
                                              По поводу интерактива: нет ничего, что можно сделать на JS и нельзя на ObjC. Серьезно.

                                              Я в этом ничуть не сомневаюсь. Но разница в том, что если нам понадобится добавить произвольный интерактив для произвольной книги, нужно будет всего лишь добавить JS-файл в epub. Что вы будете делать в этом случае? Вместо текста отдавать бинарник?
                                    +1
                                    Спасибо за приложение!!!
                                    На данный момент оно может стать моей дефолтной читалкой, если сделаете версию для левшей (тапзоны наоборот):-)).

                                    А в остальное настолько все грамотно, быстро и без всего лишнего, что просто диву даешься.
                                    Просто молодцы!!!
                                      0
                                      Очень крутая задача.
                                        0
                                        даже удивительно — у остальных читалок на iOS уходит где-то от 6-7 секунд (и больше) на то чтоб запуститься и открыть книгу, эта грузится за две.

                                        но все же выравнивания по ширине и ночного режима не хватает.
                                          0
                                          точнее — не хватает кнопки ночного режима где-то сразу под рукой, а не в меню настройки шрифтов.
                                          0
                                          быстродействие действительно поражает. тот же shortbook теперь кажется неповоротливым монстром. и поиск кинг в приложении организован очень удобно.
                                          спасибо, буду пользоваться вашим сервисом.
                                            0
                                            Чем libXML лучше NSXMLParser, и почему не использовали его?
                                              0
                                              Всем. Погуглите NSXMLParser и в основном вы будете находить советы выкинуть его и использовать LibXML.
                                                0
                                                Ничем не лучше, т.к. NSXMLParser сам использует libxml. Другое дело, что нам нужно парсить именно HTML, точнее, фрагменты HTML, которые не являются валидным XML в общем случае. NSXMLParser с ними не справляется.
                                              • UFO just landed and posted this here
                                                  0
                                                  Анализировать целый абзац имеет смысл только при выравнивании текста по обоим краям (justified), для выключки влево это ни к чему. Но его нужно делать только с переносами, а их я сделать просто не успел. Системе переносов нужно знать, на каком языке каждое слово (в идеале) и как минимум — на каком языке книга. Мы еще не решили как это лучше сделать, поэтому не стали спешить. По-моему, лучше это сделать позже, но сразу хорошо.
                                                  • UFO just landed and posted this here
                                                    • UFO just landed and posted this here
                                                        0
                                                        Построчные вычисления однозначно быстрее. Другой вопрос – насколько. Если время обработки абзаца меньше O(n), где n – число строк, можно попробовать сделать совсем круто, как у Кнута. Если нет, можно упереться в абзацы размером в десятки тысяч символов. Мне еще предстоит получше изучить мат. часть.
                                                        • UFO just landed and posted this here
                                                    0
                                                    ммм, а почему бы данные о глифах напрямую у freetype не спросить? Наверняка CGFontGetGlyphsForUnichars так и поступает где-то глубоко внутри… В принципе, рисовать текст тоже можно вручную, закешировав глифы в битмапы на лету.
                                                      +1
                                                      Так мы и делаем. Только глифы в битмапах не кэшируем, т.к. 1) на это нужно достаточно много памяти, 2) Core Graphics рисует глифы с невероятной скоростью и 3) поддержка iPhone 4 с его чудо-дисплеем достается нам автоматически, вообще ничего для этого делать не требуется.
                                                      0
                                                      На iPad хорошо смотрится.
                                                        0
                                                        Отличное приложение. Спасибо!
                                                          0
                                                          Эхх, вы реализовали то, что я хотел сделать еще где-то год-пол года назад. Но в тот момент меня отговорили некоторые личности в узких, скажем так, преподавательско-литературных кругах. Которые говорили, что сейчас это не пойдет, поскольку нет действительно удобного устройства для чтения (даже ридеры в счет не брались!). И я поверил… а жаль! :)
                                                          Все равно — удачи вам! Я бы добавил из своих идей еще платную подписку на журналы/газеты. Свяжитесь с издательствами (многие наши соотечественники хотели бы читать местную прессу, проживая далеко от родных краев), они пойдут вам на встречу.
                                                            +1
                                                            Хм… Вы говорите об обычной читалке книжек? Еще год-полтара назад их были тучи в том же Apple store
                                                              0
                                                              Нет, я говорю о всем проекте в целом (Bookmate). Что человек может «накачать» себе нужных книжек в «кабинет» и с любого девайса, который ему удобен читать их. Bookmate — это один в один то, что я хотел сделать. :)
                                                                0
                                                                Понял, сорри за наезд.
                                                                  0
                                                                  Никаких проблем, бро! ;)
                                                            0
                                                            Думаю вы спасли по крайней мере одну жизнь:)
                                                              0
                                                              Интересный дизайн приложения. Хочу такое на iPad.
                                                              А на странице инфо по книге не работает кнопка закачки.
                                                                –1
                                                                Шрифтов на ифоне немного. Как вариант — можно сделать лукап-таблицу, в которой хранятся размеры и вычислять размеры на ее основе.

                                                                По идее должно быть быстро.

                                                                Вопрос, тем, кто скачивал — оптимизировано ли приложение по графике и иконке под 4-й ифон?
                                                                  +1
                                                                  С iPhone 4 есть косметические проблемы, исправим в ближайшем обновлении.
                                                                  +3
                                                                  Я решал такую задачу и обломался — тогда еще не было CoreText. 6 секунд — это фантастика, коллеги! Супер, поздравляю!
                                                                    0
                                                                    Благодарности разработчикам. Приложение уже совместимо с айпадом или планируете? Это же нереальная красота, как представлю
                                                                      0
                                                                      Версия для iPad в разработке, но я пока не могу сказать, будет это отдельная программа или универсальное приложение, работающее и на iPhone, и на iPad.
                                                                        0
                                                                        Очень ждем. Думаю, версию для iPad стоит продавать. Потому что это уже мега вещь. Куплю обязательно, ну или скачаю бесплатно (как решите), давайте скорее :) И коммерческих успехов вам
                                                                          0
                                                                          Оч ждем
                                                                          0
                                                                          С айпада можно читать и онлайн.
                                                                          Вот только перелистывание сделано неудобно — лучше бы сделать по две кнопки листания с кажлой стороны, чтобы можно было листать одной рукой.
                                                                          0
                                                                          А почему так медленно выходит iPAD-версия? Там же к разрешению мало что цепляется, по идее, должно заработать почти сразу…
                                                                            0
                                                                            ой, уже увидел ответ. Сорри.

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