<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ByteFlow</title>
	<atom:link href="http://byteflow.hackndev.org/blog/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://byteflow.hackndev.org/blog</link>
	<description>записки девелоперов</description>
	<lastBuildDate>Sat, 08 Aug 2009 16:56:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Кофе, код и немного каппучино</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/08/%d0%ba%d0%be%d1%84%d0%b5-%d0%ba%d0%be%d0%b4-%d0%b8-%d0%bd%d0%b5%d0%bc%d0%bd%d0%be%d0%b3%d0%be-%d0%ba%d0%b0%d0%bf%d0%bf%d1%83%d1%87%d0%b8%d0%bd%d0%be/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/08/%d0%ba%d0%be%d1%84%d0%b5-%d0%ba%d0%be%d0%b4-%d0%b8-%d0%bd%d0%b5%d0%bc%d0%bd%d0%be%d0%b3%d0%be-%d0%ba%d0%b0%d0%bf%d0%bf%d1%83%d1%87%d0%b8%d0%bd%d0%be/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 16:37:29 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=245</guid>
		<description><![CDATA[
Это лето какое-то насыщенное на всяческого рода девелоперские мероприятия. Совсем недавно прошла &#8220;ифоновка&#8221;, а сегодня мне посчастливилось попасть на первую встречу Coffee&#38;Code.
Данный ивент проводился без какой-либо конкретной фиксированной направленности, но так вышло, что сегодня все говорили, в основном, про веб-технологии. Открыл конференцию Андрей Легаев с рассказом про кросс-доменные хаки. Впрочем, начало доклада прошло в поисках [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-246" title="coffeencode" src="http://byteflow.hackndev.org/blog/wp-content/uploads/2009/08/coffeencode.jpg" alt="coffeencode" width="450" height="337" /></p>
<p>Это лето какое-то насыщенное на всяческого рода девелоперские мероприятия. Совсем недавно прошла &#8220;ифоновка&#8221;, а сегодня мне посчастливилось попасть на <a href="http://coffee-n-code.org.ua/2009/07/27/первая-встреча-coffeencode/" onclick="pageTracker._trackPageview('/outgoing/coffee-n-code.org.ua/2009/07/27/_-_-coffeencode/?referer=');">первую встречу Coffee&amp;Code</a>.</p>
<p>Данный ивент проводился без какой-либо конкретной фиксированной направленности, но так вышло, что сегодня все говорили, в основном, про веб-технологии. Открыл конференцию Андрей Легаев с рассказом про кросс-доменные хаки. Впрочем, начало доклада прошло в поисках учебного центра Luxoft, где было мероприятие, но окончание оказалось весьма интересным.</p>
<p>Вторым выступал Олег Смирнов, который рассказал на примерах о jQuery. Очень интересная тема, но неподготовленному пользователю напоминала набор страшноватых хаков и оберток. Впрочем, аудитория материал восприняла.</p>
<p>Третьим выпустили меня, и я на фоне рассказа о jQuery продемонстрировал Cappuccino. Вроде, получилось неплохо, правда я теперь всерьез настроился на поиск и приобретение MDP-to-VGA, потому как зависеть от чужих железок очень неприятно и неудобно.</p>
<p>Завершил мероприятие Андрей Савченко, который рассказал нам о &#8220;ленивых RoR девелоперах&#8221; и Capistrano. Проект интересный, и, я думаю, заслуживает внимания не только RoR-разработчиков.</p>
<p>Всем докладчикам раздали кружки с официальной символикой – мелочь, а приятно.</p>
<p>На твиттере обзор можно найти по хештегам <a href="https://twitter.com/search?q=%23coffeencode" onclick="pageTracker._trackPageview('/outgoing/twitter.com/search?q=_23coffeencode&amp;referer=');">#coffeencode</a> и <a href="https://twitter.com/search?q=%23coffencode" onclick="pageTracker._trackPageview('/outgoing/twitter.com/search?q=_23coffencode&amp;referer=');">#coffencode</a> (ифон решил, что словарь умнее меня).</p>
<p>PS: огромное спасибо <a href="http://twitter.com/pfactum" onclick="pageTracker._trackPageview('/outgoing/twitter.com/pfactum?referer=');">@pfactum&#8217;у</a> за вычитку и исправления.</p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/08/%d0%ba%d0%be%d1%84%d0%b5-%d0%ba%d0%be%d0%b4-%d0%b8-%d0%bd%d0%b5%d0%bc%d0%bd%d0%be%d0%b3%d0%be-%d0%ba%d0%b0%d0%bf%d0%bf%d1%83%d1%87%d0%b8%d0%bd%d0%be/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iDCUa &#8211; как оно было</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/07/idcua-%d0%ba%d0%b0%d0%ba-%d0%be%d0%bd%d0%be-%d0%b1%d1%8b%d0%bb%d0%be/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/07/idcua-%d0%ba%d0%b0%d0%ba-%d0%be%d0%bd%d0%be-%d0%b1%d1%8b%d0%bb%d0%be/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 19:55:42 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[Записки]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=237</guid>
		<description><![CDATA[
Наконец у меня дошли руки до обзора прошедшего сегодня в Киеве iPhone Developer Camp. Пока я разгреб все визитки, фолловеров в твиттере и прочее, наконец мысли собрались в кучу.
Ивент прошел на высоте. Лично я очень доволен. Огромное спасибо Павлу, Андрею и остальным организаторам (Павел правда пропал с моего доклада унеся с собой &#8220;артефактный&#8221; ифон, но [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.iphonedev.com.ua/wp-content/uploads/2009/06/iphonedevcampua.jpg" alt="" /><br />
Наконец у меня дошли руки до обзора прошедшего сегодня в Киеве <a href="http://www.iphonedev.com.ua/iphonedevcamp-ukraine" onclick="pageTracker._trackPageview('/outgoing/www.iphonedev.com.ua/iphonedevcamp-ukraine?referer=');">iPhone Developer Camp</a>. Пока я разгреб все визитки, фолловеров в твиттере и прочее, наконец мысли собрались в кучу.</p>
<p>Ивент прошел на высоте. Лично я очень доволен. Огромное спасибо Павлу, Андрею и остальным организаторам (Павел правда пропал с моего доклада унеся с собой &#8220;артефактный&#8221; ифон, но мы выкрутились).</p>
<p>Педагогический Университет им. Гринченка оказался внутри вполне ничего. Жарко было, особенно под конец, да вода кончилась, но литр гинесса после вернул в меня радость жизни. Но это я уже забегаю далеко&#8230;</p>
<p>Wifi глюкал основательно, что вызвало несколько проблем (как вам роутинг: мой macbook держит wifi, по eth отдает его на <a href="http://twitter.com/darkproger" onclick="pageTracker._trackPageview('/outgoing/twitter.com/darkproger?referer=');">@darkproger</a>&#8216;овский IBM, который держит свой AP куда прицеплен мой iPhone? И один фиг не сработало как надо). Места было мало, но это понятно &#8211; очень много заинтересованных посетителей.</p>
<p>Доклад Славика Бубнова &#8211; &#8220;Обзор фреймворков в iPhone SDK“ я послушать не смог, был занят кейнотой на своем маке (который во второй аудитории стоял презентационным), но отзывы были очень положительные. Тарас Филатов, которому я помог со слайдами, рассказал про “опыт становления как iPhone разработчиков &#8211; пример компании Injoit“, интересный доклад, но там явно не хватало звукового сопровождения. &#8220;Танчики&#8221; у них замечательные вышли.</p>
<p>После доклада я выяснил что 1) Keynote Remote платный ($0.99) 2) у меня заблочили кредитку в аппсторе. Посему эту ценную програмку я вытянул с аппюлуса, чем заслужил несколько едких комментариев в свой адрес. Пока Сергей Вольский рассказывал о “дальнейших шагах после разработки iPhone приложения“ (каюсь, не слушал), я проникался “Objective-C 2.0: кратким описанием языка и рантайма“ в исполнении Андрея Козачука. Очень понравилось, смог вставить несколько раз свои пять центов и был доволен фидбеком.</p>
<p>Вернувшись в аудиторию второго потока, я коротко пообщался с Александром Каверином на тему его доклада (“Топ 10 ошибок при разработке iPhone приложения“), пришел к выводу что для меня это уже пройденный этап и пошел снова в первую аудиторию. По дороге туда с моей футболки (с надписями SYN и ACK, идея <a href="http://twitter.com/darkproger" onclick="pageTracker._trackPageview('/outgoing/twitter.com/darkproger?referer=');">@darkproger</a>&#8216;а) сняли фотографии и прокомментировали ее идейность. Тайкало Павел рассказал про “хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)“, где я сначала вставлял замечания про SQLite-PO (коммитером которого я являюсь), а потом еще немного затронул тему портируемости. С чуством выполненного долга <a href="http://twitter.com/darkproger" onclick="pageTracker._trackPageview('/outgoing/twitter.com/darkproger?referer=');">@darkproger</a>, гость столицы и я отправились обедать в кафешку, когда-то давно показанную мне <a href="http://twitter.com/simonoff" onclick="pageTracker._trackPageview('/outgoing/twitter.com/simonoff?referer=');">@devil</a>&#8216;ом, а остальные разбрелись кто куда. Подход баркемпов к общению (или это я просто к всем влазил и надоедал?..) мне положительно нравился.</p>
<p>Обед подошел к концу, Александр Кукла пошел рассказывать про Unit-тестирование на ифоне, а мы с <a href="http://twitter.com/darkproger" onclick="pageTracker._trackPageview('/outgoing/twitter.com/darkproger?referer=');">@darkproger</a>&#8216;ом сели настраивать проектор и окружение под нашу презентацию. Потенциальные &#8220;Light talks&#8221; переросли в небольшой островок дискуссии, где темой разговора был в основном профит (вернее пути к получению денег от эппла в наших тяжелых украинских условиях). Так или иначе, но часы подошли к отметке 14:50, и я резко перешел в &#8220;лекторский&#8221; режим. По времени и покрытию тем мы почти вписались, но в один момент (когда <a href="http://twitter.com/darkproger" onclick="pageTracker._trackPageview('/outgoing/twitter.com/darkproger?referer=');">@darkproger</a> заговорил про криптоалгоритмы в SSL) у меня появилось ощущение, что палку мы немного перегнули. Впрочем наша группа поддержки сидела на пятом ряду, улыбалась, и давала понять что все идет отлично. Wifi отвалился, но life:) отлично вытерпел не только несколько пуш-пакетов, но и VNC-сессию, с помощью которой на проекторе мы показали Push-уведомления вживую. Видимо кода у нас было болше всех, так как ссылками на репозитории мы забили целую страницу H&amp;D&#8217;шной секции про ифоны (с неизменным артворком <a href="http://twitter.com/genn_org" onclick="pageTracker._trackPageview('/outgoing/twitter.com/genn_org?referer=');">@genn_org</a>&#8216;а).</p>
<p>Но что это я все о своем&#8230; После нашего доклада я пошел слушать про кросс-платформенность между iPhone и Windows в исполнении Тараса Товченко. Немного потроллил. Привел прожера, он проникся темой неудачности GCC для винды и мы еще немного потроллили вместе. К сожалению практический смысл разработок Тараса от меня ускользнул (даже после последующего общения с ним), но масштабы потенциальных планов впечатлили.</p>
<p>Про доклады Александра Краковецкого (“Принципы разработки ПО для iPhone с использованием акселерометра“) и Дмитрия Карпецова (“Правила разработки ПО от Apple или Human Interface Guidelines“) ничего сказать не могу &#8211; ничего не слышал. На твиттере про последний писали &#8220;интересно, но монотонно&#8221;.</p>
<p>Афтерпати прошло в замечательном заведении на краю цивилизации, где было замечательное пиво, замечательная закуска, замечательные кондиционеры и замечательные лавочки :)</p>
<p>Дух девкампа мне очень понравился, много людей с которыми я постараюсь поддерживать и дальнейшие контакты. Много людей пришли без особых знаний в разработке под ифон вообще и просили howto&#8217;шки и туториалы. Нескольких интересовали вопросы разработки вне пределов SDK (т.е. на jailbreak-нутых телефонах). Почему-то абслютно никто не задавался вопросами разработки под OSX, меня это немного удивило.</p>
<p>В таком же формате повторять ивент раньше чем через год (ну пол-года) наверно не стоит. Но небольшие пятиминутки a la последняя питоновка, которую устроил <a href="http://twitter.com/maxua" onclick="pageTracker._trackPageview('/outgoing/twitter.com/maxua?referer=');">Максим Ищенко</a> вполне прижились бы на более частой основе. Тем много, и заинтересованных людей хватает.</p>
<p>PS: данный очерк &#8211; все же личные представления о прошедшем девкемпе, но в более официальной форме написать его у меня не вышло бы &#8211; именно в таком духе проходил ивент. It was fun.</p>
<p>PPS: <a href="http://www.flickr.com/photos/leprik/sets/72157621513501787/" onclick="pageTracker._trackPageview('/outgoing/www.flickr.com/photos/leprik/sets/72157621513501787/?referer=');">Фотографии с ивента</a></p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/07/idcua-%d0%ba%d0%b0%d0%ba-%d0%be%d0%bd%d0%be-%d0%b1%d1%8b%d0%bb%d0%be/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Программа OpenKyiv 2009</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/07/%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0-openkyiv-2009/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/07/%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0-openkyiv-2009/#comments</comments>
		<pubDate>Sun, 12 Jul 2009 06:04:47 +0000</pubDate>
		<dc:creator>Владимир Кириллов</dc:creator>
				<category><![CDATA[Записки]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=234</guid>
		<description><![CDATA[Опубликована программа конференции OpenKyiv 2009!
Конференция пройдет, как и в прошлом году, в Доме Учителя по адресу г. Киев, ул. Владимирская 57, начало регистрации &#8211; 9:00, начало выступлений &#8211; 10:00.
Приходите заранее!
А мы же продолжаем подготовку, следите за новостями на сайте!
Удачи и до встречи на конференции!
новость: http://uaoug.org.ua/news/openkyiv2009_program/
программа: http://uaoug.org.ua/openkyiv/2009/program/
]]></description>
			<content:encoded><![CDATA[<blockquote><p>Опубликована программа конференции OpenKyiv 2009!<br />
Конференция пройдет, как и в прошлом году, в Доме Учителя по адресу г. Киев, ул. Владимирская 57, начало регистрации &#8211; 9:00, начало выступлений &#8211; 10:00.<br />
Приходите заранее!</p>
<p>А мы же продолжаем подготовку, следите за новостями на сайте!<br />
Удачи и до встречи на конференции!</p></blockquote>
<p>новость: <a href="http://uaoug.org.ua/news/openkyiv2009_program/" onclick="pageTracker._trackPageview('/outgoing/uaoug.org.ua/news/openkyiv2009_program/?referer=');">http://uaoug.org.ua/news/openkyiv2009_program/</a><br />
программа: <a href="http://uaoug.org.ua/openkyiv/2009/program/" onclick="pageTracker._trackPageview('/outgoing/uaoug.org.ua/openkyiv/2009/program/?referer=');">http://uaoug.org.ua/openkyiv/2009/program/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/07/%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0-openkyiv-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenKyiv 2009 Call for Papers</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/05/openkyiv-2009-call-for-papers/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/05/openkyiv-2009-call-for-papers/#comments</comments>
		<pubDate>Sat, 09 May 2009 07:35:20 +0000</pubDate>
		<dc:creator>Владимир Кириллов</dc:creator>
				<category><![CDATA[Записки]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=230</guid>
		<description><![CDATA[Начата активная подготовка к BSD-конференции OpenKyiv 2009, открыта регистрация.
Мы рады объявить начало периода сбора докладов на конференцию OpenKyiv. Докладчики приглашаются предоставить на рассмотрение свои работы, посвященные OpenBSD. OpenKyiv &#8211; единственная регулярная конференция BSD на пост-советском пространстве, проходящая в Киеве.
Просмотрите страницу конференции для получения более подробной информации, регистрации, а также деталей о предстоящих событиях.

регистрация: http://uaoug.org.ua/openkyiv/2009/register
информация по [...]]]></description>
			<content:encoded><![CDATA[<p>Начата активная подготовка к BSD-конференции OpenKyiv 2009, открыта регистрация.</p>
<blockquote><p>Мы рады объявить начало периода сбора докладов на конференцию OpenKyiv. Докладчики приглашаются предоставить на рассмотрение свои работы, посвященные OpenBSD. OpenKyiv &#8211; единственная регулярная конференция BSD на пост-советском пространстве, проходящая в Киеве.</p>
<p>Просмотрите страницу конференции для получения более подробной информации, регистрации, а также деталей о предстоящих событиях.
</p></blockquote>
<p>регистрация: <a href="http://uaoug.org.ua/openkyiv/2009/register" onclick="pageTracker._trackPageview('/outgoing/uaoug.org.ua/openkyiv/2009/register?referer=');">http://uaoug.org.ua/openkyiv/2009/register</a><br />
информация по сбору: <a href="http://uaoug.org.ua/openkyiv/2009/callforpapers" onclick="pageTracker._trackPageview('/outgoing/uaoug.org.ua/openkyiv/2009/callforpapers?referer=');">http://uaoug.org.ua/openkyiv/2009/callforpapers</a><br />
общая информация по конференции: <a href="http://uaoug.org.ua/openkyiv/2009" onclick="pageTracker._trackPageview('/outgoing/uaoug.org.ua/openkyiv/2009?referer=');">http://uaoug.org.ua/openkyiv/2009</a></p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/05/openkyiv-2009-call-for-papers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Byteflow, нам уже 9 месяцев!</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/02/byteflow-%d0%bd%d0%b0%d0%bc-%d1%83%d0%b6%d0%b5-7-%d0%bc%d0%b5%d1%81%d1%8f%d1%86%d0%b5%d0%b2/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/02/byteflow-%d0%bd%d0%b0%d0%bc-%d1%83%d0%b6%d0%b5-7-%d0%bc%d0%b5%d1%81%d1%8f%d1%86%d0%b5%d0%b2/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 23:55:48 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[ByteFlow]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=227</guid>
		<description><![CDATA[Очень разует что нас читают. Значит пишем полезные вещи! Значит людям это интересно.
Итод по сайтам, с которых попадают на byteflow: лидирует личный сайт Владимира Кириллова, почти догнал его сайт украинского сообщества программистов (Макс, спасибо что пригласил в ленту!), четвертым (DOU заняло 2 и 3 позиции по двум ссылкам) идет Google Reader и подводит итог пятерке [...]]]></description>
			<content:encoded><![CDATA[<p>Очень разует что нас читают. Значит пишем полезные вещи! Значит людям это интересно.</p>
<p>Итод по сайтам, с которых попадают на byteflow: лидирует личный сайт <a href="http://darkproger.net/" onclick="pageTracker._trackPageview('/outgoing/darkproger.net/?referer=');">Владимира Кириллова</a>, почти догнал его <a href="http://developers.org.ua" onclick="pageTracker._trackPageview('/outgoing/developers.org.ua?referer=');">сайт украинского сообщества программистов</a> (Макс, спасибо что пригласил в ленту!), четвертым (DOU заняло 2 и 3 позиции по двум ссылкам) идет <a href="http://google.com/reader" onclick="pageTracker._trackPageview('/outgoing/google.com/reader?referer=');">Google Reader</a> и подводит итог пятерке <a href="http://hackndev.org" onclick="pageTracker._trackPageview('/outgoing/hackndev.org?referer=');">иформационная страничка проектов Hack&#038;Dev</a>.</p>
<p>Поисковые запросы, приводящие на byteflow вполне закономерны. С существенным отрывом идет термин &#8220;objective-c&#8221;. На втором месте &#8211; &#8220;мировой чат&#8221; (наш конспиратор rilian &#8211; гений, написал <a href="http://byteflow.hackndev.org/blog/index.php/2008/08/world-chat-with-set-language/">заметку</a> почти ни о чем, а она срывает все сливки). Далее собственно &#8220;byteflow&#8221; (русский и украинский варианты гугла отдают ссылку на нас на первой странице), &#8220;wchar_t&#8221; и &#8220;cocotron&#8221;.</p>
<p>Самые читаемые статьи: <a href="http://byteflow.hackndev.org/blog/index.php/2008/09/mac-os-пол-года-спустя/">моя заметка о ПО для OSX</a>, <a href="http://byteflow.hackndev.org/blog/index.php/2008/10/динамические-древовидные-меню-на-iphone/">еще моя заметка про меню на iPhone</a>, <a href="http://byteflow.hackndev.org/blog/index.php/2008/06/objective-c-зачем-оно-и-с-чем-его-есть/">снова моя заметка о Obj-C</a>, ну и наконец страница обо мне и о Владимире Кириллове. Мировые чаты &#8211; это хорошо, но не достаточно :)</p>
<p>620 хитов за январь по данным wordpress.com и 390 &#8211; по google analytics. Из чего следует, что половина пользователей гуглового аналитика режет как баннер :)</p>
<p>Треть пользователей остается с нами. Это радует, хотя ставит под сомнение количество читающих на feedburner&#8217;е. Если не RSS &#8211; как сюда попадают?</p>
<p>Пользователей Firefox на Windows и Safari на Mac почти поровну. Блог читают даже пользователи OpenBSD, и я знаю кто. :)</p>
<p>Статистика по хитам с гугловой аналитики подтверждает цифры с wordpress.com.</p>
<p>Несколько выводов для отображения общей картины, в форме тезисов. Блог полезен не только нам. По Objective-C на русском информации мало. Мировой чат &#8211; актуальна тема.</p>
<p>Постараемься и дальше радовать старых и новых читателей, хотя многие статьи выглядят скорее короткими заметками, в других часто путается логичность изложения, ну и у меня хромает грамматика русского языка или пальцы бегают мимо нужных букв (за остальными авторами не замечал). :)</p>
<p>PS: WP&#8217;шный интерфейс для создания постов ужасно неудобен при больших объемах стати. Надо придумать какую-то реальную замену, TextMate нагрузить снова что-ли?..</p>
<p>PPS: хм, пересчитал месяца по архиву &#8211; получилось не семь, а девять. Ночью спать надо, а не заметки писать&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/02/byteflow-%d0%bd%d0%b0%d0%bc-%d1%83%d0%b6%d0%b5-7-%d0%bc%d0%b5%d1%81%d1%8f%d1%86%d0%b5%d0%b2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cappuccino, из чего состоит программа</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/02/cappuccino-%d0%b8%d0%b7-%d1%87%d0%b5%d0%b3%d0%be-%d1%81%d0%be%d1%81%d1%82%d0%be%d0%b8%d1%82-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/02/cappuccino-%d0%b8%d0%b7-%d1%87%d0%b5%d0%b3%d0%be-%d1%81%d0%be%d1%81%d1%82%d0%be%d0%b8%d1%82-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 21:11:17 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Objective-J]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=223</guid>
		<description><![CDATA[Сделал небольшой перерыв на осмысление задачи, на которой бы демонстрировал Cappuccino, под руку подвернулось задание с собеседования на Bindows. Вкратце &#8211; сделать адресную книгу на базе данных в xml.
В этой статье я рассмотрю элементы программы на Cappuccino, а далее приступим к моментам практической реализации.
И так, новый проект на Cappuccino состоит из следующих файлов.
index.html и index-debug.html. [...]]]></description>
			<content:encoded><![CDATA[<p>Сделал небольшой перерыв на осмысление задачи, на которой бы демонстрировал Cappuccino, под руку подвернулось задание с собеседования на Bindows. Вкратце &#8211; сделать адресную книгу на базе данных в xml.</p>
<p>В этой статье я рассмотрю элементы программы на Cappuccino, а далее приступим к моментам практической реализации.<span id="more-223"></span></p>
<p>И так, новый проект на Cappuccino состоит из следующих файлов.<br />
<strong>index.html</strong> и <strong>index-debug.html</strong>. Это точки запуска веб-приложения. Отличаются друг от друга только путями поиска библиотек (в index-debug отладочные версии идут первыми). Содержимое файлов отображается в броузере пока необходимые для работы программы файлы не загрузятся, после чего содержимое будет полностью удалено и управление содержимым окна полностью перейдет к Cappuccino.</p>
<p><strong>main.j</strong>. Как и в С, в objective-J программа начинается с функции main. Единственная задача main &#8211; запустить собственно Cappuccino. Как рантайм узнает, кому передавать управление? Очень просто:</p>
<p><strong>Info.plist</strong> описывает несколько важных параметров, один из которых, CPApplicationDelegateClass &#8211; имя класса выступаещего делегатом приложения. Экземпляр именно этого класса получит сообщение  <em>applicationDidFinishLaunching:</em>. Обращу ваше внимание на то, что main.j содержит следующую строчку:</p>
<pre lang="objc">
@import "AppController.j"
</pre>
<p>без этого класс не загрузится, и рантайм не будет знать, где его искать.</p>
<p><strong>AppController.j</strong> содержит реализацию делегата программы. Собственно именно тут и начинается магия Cappuccino, прямо с <em>applicationDidFinishLaunching:</em>.</p>
<p>В отличие от Objective-C, в Objective-J нет описания классов (interface), только реализация (implementation). Список переменных класса соответственно перенесен в реализацию.</p>
<p>В коде по умолчанию контроллер создает окно на весь экран и в нем лейбл &#8220;Hello world&#8221;. Безжалостно уничтожим этот код :)</p>
<p>Наше главное окно будет содержать список контактов в виде, похожем на Address Book из OSX: слева список контактов, справа &#8211; вид карточки. Начнем с описания полноценного перемещаемого окна:</p>
<pre lang="objc">
@implementation AppController : CPObject
{
    CPWindow contactsWindow;
}

- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
    // initialize primary window
    contactsWindow = [[CPWindow alloc]
                      initWithContentRect:CPMakeRect(50,50,600,300)
                      styleMask:CPTitledWindowMask|CPResizableWindowMask|CPTexturedBackgroundWindowMask];
    [contactsWindow setTitle:@"Address Book"];
    [contactsWindow setMinSize:CPMakeSize(400,300)];
    var cwView = [contactsWindow contentView];
}</pre>
<p>Ссылка на основное окно нам еще пригодится, потому мы сохраним ее в ivar нашего контроллера. Все что нам не пригодится &#8211; описываем локально (например cwView). JavaScript &#8211; язык не типизированный, так что вместо типа переменной необходимо писать JS&#8217;ный var.</p>
<p>Еще одно замечание насчет документации и поиска методов у классов &#8211; очень советую поставить doxygen и перегенерить доки (ant documentation). На сайте они устарели. Кроме того я на днях нашел проблему с пропаданием методов (doxygen вообще использует синтаксис Obj-C, и на некоторых местах его парсер ломается), так что на днях надеюсь допинать апстрим новой, более полной документацией.</p>
<p>И так, мы создали новое окно в заданном прямоугольнике, с заголовком (CPTitledWindowMask), возможностью изменять размер (CPResizableWindowMask) и текстурированным фоном (CPTexturedBackgroundWindowMask). Так же задали текст заголовка и минимальный размер. Для полного счастья можно попросить окно появиться:</p>
<pre lang="objc">[contactsWindow orderFront:self];</pre>
<p>и запустив index.html поигратся с перетягиванием и изменением размера пустого и пока что совершенно бесполезного окна. Хотя неплохо, как для четырех строчек.</p>
<p>Теперь рассмотрим, как нам получить и обработать данные с сервера. Для этого мы заведем новый класс ABManager, производный от CPObject в файле ABManager.j. Поскольку оригинальный xml распарсить можно только средствами JS, то я решил прикрутить немного XSLT, для того чтобы больше раскрыть работу с объектами и немного KVC (Key-Value Coding) Cappuccino. Код получился не очень красивый и отягощенный поддержкой гадкого IE.</p>
<p>Исходный XML выглядит так:</p>
<pre lang="xml"><AddressBook>
	<Contact>
		<CustomerID>ALFKI</CustomerID>
		<CompanyName>Alfreds Futterkiste</CompanyName>
		<ContactName>Maria Anders</ContactName>
		<ContactTitle>Sales Representative</ContactTitle>
		<Address>Obere Str. 57</Address>
		<City>Berlin</City>
		<Email>dummy@gmail.com</Email>
		<PostalCode>12209</PostalCode>
		<Country>Germany</Country>
		<Phone>030-0074321</Phone>
		<Fax>030-0076545</Fax>
	</Contact>
	<Contact>
		<CustomerID>ANATR</CustomerID>
		<CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
		<ContactName>Ana Trujillo</ContactName>
		<ContactTitle>Owner</ContactTitle>
		<Address>Avda. de la Constitución 2222</Address>
		<City>México D.F.</City>
		<Email>dummy@gmail.com</Email>
		<PostalCode>05021</PostalCode>
		<Country>Mexico</Country>
		<Phone>(5) 555-4729</Phone>
		<Fax>(5) 555-3745</Fax>
	</Contact>
	...
</AddressBook></pre>
<p>Из него надо сделать <a href="http://www.apple.com/DTDs/PropertyList-1.0.dtd" onclick="pageTracker._trackPageview('/outgoing/www.apple.com/DTDs/PropertyList-1.0.dtd?referer=');">property list</a> (plist&#8217;ы повсемесно используются как и в Макоси, так и в производной от Cocoa &#8211; Cappuccino). Делается конвертация одним простым XSLT:</p>
<pre lang="xml"><?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output encoding="UTF-8" indent="yes" method="xml" />

<xsl:template match="/AddressBook">
<plist version="1.0">
		<array>
			<xsl:apply-templates select="Contact" />
		</array>
	</plist>
</xsl:template>

<xsl:template match="/AddressBook/Contact">
	<dict>
		<xsl:apply-templates select="*" />
	</dict>
</xsl:template>

<xsl:template match="/AddressBook/Contact/*">
	<key><xsl:value-of select="name()"/></key>
	<string><xsl:value-of select="text()"/></string>
</xsl:template>

</xsl:stylesheet></pre>
<p>Тут мы сначала находим элемент AddressBook и создаем базовый тег plist и array контактов. Потом для каждого Contact мы делаем новый dict, в который через последнее правило записывем пары ключ-значение на базе имени тега. Таким образом из обработанного plist можно получить город пятого контакта путем вызова</p>
<pre lang="objc">[[contacts objectAtIndex:4] valueForKey:"City"]</pre>
<p>.</p>
<p>И так, наш ABManager. Должен уметь грузить контакты, и отдавать их список:</p>
<pre lang="objc">@implementation ABManager : CPObject
{
    CPArray _contacts;
}</pre>
<p>Для начала загрузим входной xml и xslt:</p>
<pre lang="objc">- (id)initWithXML:(CPString)path
{
    self = [super init];

    var xml = [CPURLConnection
                      sendSynchronousRequest:[CPURLRequest requestWithURL:path]
                      returningResponse:nil
                      error:nil];
    if(xml == nil)
        return nil;

    var xslt = [CPURLConnection
                sendSynchronousRequest:[CPURLRequest requestWithURL:@"abplist.xsl"]
                returningResponse:nil
                error:nil];
    if(xslt == nil)
        return nil;</pre>
<p>В Cappuccino очень просто делать синхронные или асинхронные запросы в сеть. CPURL пока что отсутствует, и вместо него следует использовать просто CPString (т.е. строку).</p>
<p>Теперь несколько кросс-броузерной магии. В начало файла добавим функцию (не забывайте &#8211; писать можно все что является правильным JS):</p>
<pre lang="js">function XmlFromString(xmlData)
{
	if (window.ActiveXObject) {
		//for IE
		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(xmlData);
		return xmlDoc;
	} else if (document.implementation &#038;&#038; document.implementation.createDocument) {
		//for Mozila
		parser=new DOMParser();
		xmlDoc=parser.parseFromString(xmlData,"text/xml");
		return xmlDoc;
	}
}</pre>
<p>XmlFromString на вход получает строку, на выходе &#8211; обработанный Document. Теперь можно получить из двух строк два документа и трансформировать xml из полученного абстрактного типа в конкретный plist:</p>
<pre lang="objc">    var xmlDoc  = XmlFromString([xml string]);
    var xsltDoc = XmlFromString([xslt string]);
    var plist = nil;

    if (window.ActiveXObject) {
        plist = xmlDoc.transformNode(xsltDoc);
        plist = plist.xml;
    } else if (document.implementation&#038;&#038; document.implementation.createDocument) {
        xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xsltDoc);
        plist = xsltProcessor.transformToFragment(xmlDoc, document);
        plist = (new XMLSerializer()).serializeToString(plist);
    } else
        return nil;</pre>
<p>А plist уже распарсит Cappuccino:</p>
<pre lang="objc">
    _contacts = [[[CPData alloc] initWithString:plist] plistObject];

    return self;
}</pre>
<p>Кстати, в данный момент в IE это не работает, там парсер plist несколько сломан. Патч <a href="http://cappuccino.lighthouseapp.com/projects/16499/tickets/216-plist-parser-fails-on-ie8-when-theres-no-dtd-header-in-xml#ticket-216-2" onclick="pageTracker._trackPageview('/outgoing/cappuccino.lighthouseapp.com/projects/16499/tickets/216-plist-parser-fails-on-ie8-when-theres-no-dtd-header-in-xml_ticket-216-2?referer=');">тут</a>, если кто тестит только в IE. На Firefox и WebKit-based все работает отлично.</p>
<p>Еще добавим getter-метод для нашего списка контактов и получим вот такой вот ABManager.j:</p>
<pre lang="objc">@import <Foundation/CPObject.j>

/*!
    Helper function to load xml documents
*/
function XmlFromString(xmlData)
{
	if (window.ActiveXObject) {
		//for IE
		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(xmlData);
		return xmlDoc;
	} else if (document.implementation &#038;&#038; document.implementation.createDocument) {
		//for Mozila
		parser=new DOMParser();
		xmlDoc=parser.parseFromString(xmlData,"text/xml");
		return xmlDoc;
	}
}

/*!
    Core class that manages address book. It loads given ab.xml, converts it
    into plist and stores in contacts.
*/
@implementation ABManager : CPObject
{
    CPArray _contacts;
}

/*!
    Used to initialize ABController
    @param path path to XML document with contacts data
*/
- (id)initWithXML:(CPString)path
{
    self = [super init];

    var xml = [CPURLConnection
                      sendSynchronousRequest:[CPURLRequest requestWithURL:path]
                      returningResponse:nil
                      error:nil];
    if(xml == nil)
        return nil;

    var xslt = [CPURLConnection
                sendSynchronousRequest:[CPURLRequest requestWithURL:@"abplist.xsl"]
                returningResponse:nil
                error:nil];
    if(xslt == nil)
        return nil;

    // now some js crap to convert xml :)
    var xmlDoc  = XmlFromString([xml string]);
    var xsltDoc = XmlFromString([xslt string]);
    var plist = nil;

    if (window.ActiveXObject) {
        plist = xmlDoc.transformNode(xsltDoc);
        plist = plist.xml;
    } else if (document.implementation&#038;&#038; document.implementation.createDocument) {
        xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xsltDoc);
        plist = xsltProcessor.transformToFragment(xmlDoc, document);
        plist = (new XMLSerializer()).serializeToString(plist);
    } else
        return nil;

    _contacts = [[[CPData alloc] initWithString:plist] plistObject];

    return self;
}

/*!
    Just a getter method
*/
- (CPArray)contacts
{
    return _contacts;
}

@end</pre>
<p>(я постараюсь создать репозиторий, где в ревизиях будет история по статьям. Пока что спасайтесь копипастом).</p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/02/cappuccino-%d0%b8%d0%b7-%d1%87%d0%b5%d0%b3%d0%be-%d1%81%d0%be%d1%81%d1%82%d0%be%d0%b8%d1%82-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cappuccino, часть первая</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/01/cappuccino-%d1%87%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b5%d1%80%d0%b2%d0%b0%d1%8f/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/01/cappuccino-%d1%87%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b5%d1%80%d0%b2%d0%b0%d1%8f/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 12:45:57 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[Cappuccino]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=218</guid>
		<description><![CDATA[Я хочу попробовать написать цикл статей, в которых пропробую раскрыть функциональный возможности новой интересной платформы Cappuccino.
Для начала, краткое введение в курс дела. Cappuccino &#8211; это веб фреймворк, который упрощает создание полнофункциональных клиентских веб-приложений, которые работают в броузере.

Cappuccino основан на JavaScript и реализует часть общеупобребляемых API из GNUstep и Apple Cocoa. При программировании на Cappuccino, разработчик [...]]]></description>
			<content:encoded><![CDATA[<p>Я хочу попробовать написать цикл статей, в которых пропробую раскрыть функциональный возможности новой интересной платформы Cappuccino.</p>
<p>Для начала, краткое введение в курс дела. <a href="http://www.cappuccino.org/" onclick="pageTracker._trackPageview('/outgoing/www.cappuccino.org/?referer=');">Cappuccino</a> &#8211; это веб фреймворк, который упрощает создание полнофункциональных клиентских веб-приложений, которые работают в броузере.<br />
<span id="more-218"></span></p>
<p>Cappuccino основан на JavaScript и реализует часть общеупобребляемых API из GNUstep и Apple Cocoa. При программировании на Cappuccino, разработчик думает не понятиями HTML-документа, CSS или DOM модели, а окнами, видами, кнопками в конце концов.</p>
<p>Cappuccino основан на языке программирования Objective-J, который сделан по образу и подобию Objective-C как суперсет JavaScript.</p>
<p>Для примера того, как это выглядит, посмотрите на <a href="http://280slides.com/" onclick="pageTracker._trackPageview('/outgoing/280slides.com/?referer=');">280slides</a>, <a href="http://cappuccino.org/learn/demos/FlickrPhotoDemo/" onclick="pageTracker._trackPageview('/outgoing/cappuccino.org/learn/demos/FlickrPhotoDemo/?referer=');">Flickr Photo Demo</a>, <a href="http://cappuccino.org/learn/demos/FloorPlan/" onclick="pageTracker._trackPageview('/outgoing/cappuccino.org/learn/demos/FloorPlan/?referer=');">Floor Plan</a>. Очень впечатляющие демонстрации, особенно впечатляет количество написанного кода.</p>
<p>Ладно, давайте уже программить, нет ничего лучше чем пример кода. Я пишу эту статью, основываясь на том, что читатели знакомы с базовыми понятиями *NIX, у них есть git, java, и оптимально &#8211; OSX :)</p>
<p>С Cappuccino можно работать двумя путями &#8211; или скачать <a href="http://cappuccino.org/starter/" onclick="pageTracker._trackPageview('/outgoing/cappuccino.org/starter/?referer=');">пакет для начинающих</a>, или поставить свежую версию из git. Первый путь не вызывает никаких проблем, так что далее я рассматриваю только второй.</p>
<p>И так, еще раз о необходимых утилитах: git для получения репозитория, ant для сборки (минимальная версия 1.7.0), gcc (по сути только нужен только препроцессор С: cpp). Опционально &#8211; doxygen для генерации API доков, но они и так <a href="http://cappuccino.org/learn/documentation/annotated.html" onclick="pageTracker._trackPageview('/outgoing/cappuccino.org/learn/documentation/annotated.html?referer=');">есть</a> на офсайте.</p>
<p>Начинаем с того, что клонируем дерево:<br />
<code>git clone git://github.com/280north/cappuccino.git cappuccino</code></p>
<p>Теперь нужно указать Cappuccino, куда складывать собираемые файлы:<br />
<code>export STEAM_BUILD="~/temp/steam-build"</code><br />
(указанный каталог должен существовать в ФС).</p>
<p>Еще хочу отметить что Rhino (интерпретатор JavaScript) на OSX и JVM 1.6 не работает как надо (насчет остальных ОС не уверен), так что при сборке Cappuccino лучше иметь активной JVM 1.5.</p>
<p>И так, переходим в каталог с Cappuccino и выполняем сборку:<br />
<code>cd cappuccino<br />
sudo echo<br />
# (если sudo у вас в системе спрашивает пароль - то это его<br />
# закеширует на пару минут, для установки Cappuccino в /usr/local/share/<br />
ant bootstrap<br />
ant all</code></p>
<p>После этого у вас будет собранный в /usr/local/share/objj Cappuccino, и симлинки в /usr/local/bin.</p>
<p>Для того чтобы убедится, что все работает, создадим тестовый проект:<br />
<code>steam create TestApp -l</code><br />
и если все нормально, откроем index-debug.html в броузере.</p>
<p>В следующей части мы рассмотрим элементы программы на Cappuccino.</p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/01/cappuccino-%d1%87%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b5%d1%80%d0%b2%d0%b0%d1%8f/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Простое решение для HTTP-запросов</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/01/%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b5-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%bb%d1%8f-http-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/01/%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b5-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%bb%d1%8f-http-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2/#comments</comments>
		<pubDate>Sat, 10 Jan 2009 20:25:35 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=215</guid>
		<description><![CDATA[Для приложений под iPhone которые взаимодействуют с веб-сервисами актуальны запросы по HTTP для получения каких либо данных от сервера. Далее я покажу простой метод для реализации такого запроса.
Самый простой вариант &#8211; блокируемые сокеты (запрос послали, тут же его и получили). Он не может быть применен в основном потоке, так как интерфейс &#8220;залипнет&#8221;, но ничего не [...]]]></description>
			<content:encoded><![CDATA[<p>Для приложений под iPhone которые взаимодействуют с веб-сервисами актуальны запросы по HTTP для получения каких либо данных от сервера. Далее я покажу простой метод для реализации такого запроса.<span id="more-215"></span></p>
<p>Самый простой вариант &#8211; блокируемые сокеты (запрос послали, тут же его и получили). Он не может быть применен в основном потоке, так как интерфейс &#8220;залипнет&#8221;, но ничего не мешает сделать для него отдельный поток.</p>
<p>В нашей гипотетической ситуации необходим класс, который получит набор аргументов, URL, выполнит запрос на удаленном сервере и вернет какой-либо документ (предположим что сервер возвращает XML по DTD Apple Property List).</p>
<p>Объявим несколько констант:</p>
<pre lang="objc">static const NSString *kURLKey = @"__url__";
static const NSString *kErrorKey = @"__error__";
static const NSString *kSelectorKey = @"__selector__";
static const NSString *kTargetKey = @"__target__";
static const NSString *kMultipartKey = @"__multipart__";</pre>
<p>Они пригодятся в функции, которая будет создавать поток для выполнения запроса (в него можно передать только один объект &#8211; это будет NSDictionary с параметрами):</p>
<pre lang="objc">- (void)sendAsyncRequest:(NSString *)url withPayload:(NSDictionary *)post multipart:(BOOL)mp target:(id)tar selector:(SEL)sel
{
	NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithDictionary:post];
	[dic setObject:url forKey:kURLKey];
	[dic setObject:tar forKey:kTargetKey];
	[dic setObject:[NSNumber numberWithBool:mp] forKey:kMultipartKey];
	[dic setObject:[NSString stringWithUTF8String:sel_getName(sel)] forKey:kSelectorKey];
	[NSThread
	 detachNewThreadSelector:@selector(do_sendAsyncRequestWithPayload:)
	 toTarget:self
	 withObject:dic];
}</pre>
<p>Данный метод получает на вход <em>url</em запроса, аргументы к нему в <em>post</em>, флаг необходимости отправить его через <a href="http://byteflow.hackndev.org/blog/index.php/2008/12/multipartform-data-в-cocoa/">DQMultipartForm</a> в <em>mp</em>. Когда запрос будет обработан, результат бедет передан объекту <em>tar</em> через селектор <em>sel</em>, который должен принимать один объект класса NSDictionary.</p>
<p>Теперь большой и страшный кусок кода:</p>
<pre lang="objc">- (void)do_sendAsyncRequestWithPayload:(NSMutableDictionary *)d
{
	// в контексте потока нам нужно свое управление памятью
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

	NSURL *rqUrl = [NSURL URLWithString:[d objectForKey:kURLKey]];
	NSMutableURLRequest *req;
	// получаем все не-POST аргументы и удаляем их из целевого массива
	SEL sel = sel_registerName([[d objectForKey:kSelectorKey] UTF8String]);
	id target = [d objectForKey:kTargetKey];
	BOOL multipart = [[d objectForKey:kMultipartKey] boolValue];
	[d removeObjectForKey:kURLKey];
	[d removeObjectForKey:kSelectorKey];
	[d removeObjectForKey:kTargetKey];
	[d removeObjectForKey:kMultipartKey];

	// есть необходимо цеплятьданные через multipart/form-data - инициализируем DQMultipartForm и забиваем его объектами
	// (код изначально был написан под OSX Tiger, потому не использует новомодные решения ObjC)
	if(multipart) {
		DQMultipartForm *form = [[[DQMultipartForm alloc] initWithURL:rqUrl] autorelease];
		NSEnumerator *ke = [d keyEnumerator];
		NSString *k;
		while( (k = [ke nextObject]) ) {
			id obj = [d objectForKey:k];
			if([obj isKindOfClass:[NSArray class]]) {
				NSMutableArray *s = [NSMutableArray array];
				NSEnumerator *te = [obj objectEnumerator];
				NSString *t;
				while( (t = [te nextObject]) ) {
					[form addValue:t forField:[k stringByAppendingString:@"[]"]];
				}
			} else {
				[form addValue:obj forField:k];
			}
		}
		req = [[form urlRequest] retain];
	} else {
		// если у нас обычный запрос - то формируем в строку
		req = [[NSMutableURLRequest alloc] initWithURL:rqUrl];
		[req setHTTPMethod:@"POST"];
		NSMutableArray *l = [[NSMutableArray alloc] initWithCapacity:[d count]];

		NSEnumerator *ke = [d keyEnumerator];
		NSString *k;
		while( (k = [ke nextObject]) ) {
			[l addObject:[NSString stringWithFormat:@"%@=%@",
						  k,
						  [[[[d objectForKey:k] description]
							stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
							stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"]]];
		}
		NSString *reqPayload = [l componentsJoinedByString:@"&#038;"];
		[l release];
		const char *reqPayload_c = [reqPayload UTF8String];
		[req setHTTPBody:[NSData dataWithBytes:reqPayload_c length:strlen(reqPayload_c)]];
	}
	// и так, на этот момент у нас есть NSURLRequest с готовым URL и POST-данными, пора его передать серверу!
	NSURLResponse *resp;
	NSError *err;
	// вот тут мы можем провисеть некоторое время (пока придет ответ от сервера
	// но блокируется только этот поток
	NSData *respData = [NSURLConnection
						sendSynchronousRequest:req
						returningResponse:&#038;resp
						error:&#038;err];
	NSMutableDictionary *respDict = [[NSMutableDictionary alloc] init];
	if(err) {
		// если что-то не так - наверх пойдет информация об ошибке
		[respDict setObject:err forKey:kErrorKey];
	} else {
		// Иначе считаем что все в порядке и нам передали XML с корневым элементом dict.
		NSString *plistString = [[NSString alloc] initWithBytes:[respData bytes] length:[respData length] encoding:NSUTF8StringEncoding];
		[respDict release];
		respDict = [[plistString propertyList] retain];
		[plistString release];
	}

	// respDict возвращается в основной поток и передается обработчику. Его надо будет обязательно release'нуть после обработки.
	[target
	 performSelector:sel
	 onThread:[NSThread mainThread]
	 withObject:respDict
	 waitUntilDone:YES];

	[d release];

	[pool drain];
}</pre>
<p>Так, теперь как нам собственно выполнить запрос? Элементарно:</p>
<pre lang="objc">
- (void)callSomeAsyncRequestForUser:(NSNumber *)uid
{
	[self
	 sendAsyncRequest:@"http://ourserver.com/iphone-api/somequery"
	 withPayload:[NSDictionary dictionaryWithObjectsAndKeys:
				  uid, @"user_id",
				  @"1.0", @"client_version",
				  nil]
	 multipart:NO
	 target:self
	 selector:@selector(do_callSomeAsyncRequestForUser:)];
}

- (void)do_callSomeAsyncRequestForUser:(NSDictionary *)respDict
{
	NSError *err = [respDict objectForKey:kErrorKey];
	if(err) {
		// что-то пошло не так, сообщить пользователю
		...
	} else {
		// обрабатываем данные от сервера
		...
	}
	[respDict release];
}</pre>
<p>Замечания и комментарии приветствуются.</p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/01/%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b5-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%bb%d1%8f-http-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Упрощаем переход между табами в Safari</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2009/01/%d1%83%d0%bf%d1%80%d0%be%d1%89%d0%b0%d0%b5%d0%bc-%d0%bf%d0%b5%d1%80%d0%b5%d1%85%d0%be%d0%b4-%d0%bc%d0%b5%d0%b6%d0%b4%d1%83-%d1%82%d0%b0%d0%b1%d0%b0%d0%bc%d0%b8-%d0%b2-safari/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2009/01/%d1%83%d0%bf%d1%80%d0%be%d1%89%d0%b0%d0%b5%d0%bc-%d0%bf%d0%b5%d1%80%d0%b5%d1%85%d0%be%d0%b4-%d0%bc%d0%b5%d0%b6%d0%b4%d1%83-%d1%82%d0%b0%d0%b1%d0%b0%d0%bc%d0%b8-%d0%b2-safari/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 23:27:56 +0000</pubDate>
		<dc:creator>Владимир Пузанов</dc:creator>
				<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=210</guid>
		<description><![CDATA[Я думаю, всем извесно о хоткеях ⇧⌘→ и ⇧⌘← для перехода между закладками в Safari. Есть одна неприятная вещь, связанная с это комбинацией клавиш – ⌘← и ⌘→ выполняют функции кнопок Home и End на PC. Ну а Shift дополняет перемещение выделеним, что приводит к невозможности перейти в другой таб, когда курсор в текстовом поле [...]]]></description>
			<content:encoded><![CDATA[<p>Я думаю, всем извесно о хоткеях ⇧⌘→ и ⇧⌘← для перехода между закладками в Safari. Есть одна неприятная вещь, связанная с это комбинацией клавиш – ⌘← и ⌘→ выполняют функции кнопок Home и End на PC. Ну а Shift дополняет перемещение выделеним, что приводит к невозможности перейти в другой таб, когда курсор в текстовом поле (особеннораздражает при написании переводов постов, когда оригинал в соседнем табе).</p>
<p>У этой проблемы есть очень простое решение, при чем штатными средствами. Откройте панель настройки хоткеев (Preferences &#8211; Keyboard &#038; Mouse &#8211; Keyboard Shortcuts), нажмите на плюс, в приложении выберите Safari, в названии пункта меню введите &#8220;Выбрать следующую вкладку&#8221; (&#8221;Select Next Tab&#8221; в английской локали), а в хоткее укажите что-то нейтральное, например ⌥⌘→. То же самое повторите для второго пункта меню (предидущего таба).</p>
<p>Перезапустите Safari и наслаждайтесь переходом по табам без &#8220;залипаний&#8221;!<br />
<a href="http://byteflow.hackndev.org/blog/wp-content/uploads/2009/01/prefs.png"><img src="http://byteflow.hackndev.org/blog/wp-content/uploads/2009/01/prefs-300x273.png" alt="prefs" title="prefs" width="300" height="273" class="aligncenter size-medium wp-image-211" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2009/01/%d1%83%d0%bf%d1%80%d0%be%d1%89%d0%b0%d0%b5%d0%bc-%d0%bf%d0%b5%d1%80%d0%b5%d1%85%d0%be%d0%b4-%d0%bc%d0%b5%d0%b6%d0%b4%d1%83-%d1%82%d0%b0%d0%b1%d0%b0%d0%bc%d0%b8-%d0%b2-safari/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Как создать взвешенное дерево категорий с подкатегориями?</title>
		<link>http://byteflow.hackndev.org/blog/index.php/2008/12/sql-query-for-weighted-category-tree-with-subcategories/</link>
		<comments>http://byteflow.hackndev.org/blog/index.php/2008/12/sql-query-for-weighted-category-tree-with-subcategories/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 01:42:49 +0000</pubDate>
		<dc:creator>rilian</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://byteflow.hackndev.org/blog/?p=204</guid>
		<description><![CDATA[Допустим у вас есть интернет магазин, но товары в нем выводятся в одной куче &#8211; как в магазине секонд-хэнд. И вы мечтаете все отсортировать по категориям с подкатегориями. Причем категория джинсов идет перед категорией носков, а носки в добавок делятся на дырявые и обычные, ну и обычные идут первее.
Итак, вам нужно вывести взвешенный список категорий [...]]]></description>
			<content:encoded><![CDATA[<p>Допустим у вас есть интернет магазин, но товары в нем выводятся в одной куче &#8211; как в магазине секонд-хэнд. И вы мечтаете все отсортировать по категориям с подкатегориями. Причем категория джинсов идет перед категорией носков, а носки в добавок делятся на дырявые и обычные, ну и обычные идут первее.</p>
<p>Итак, вам нужно вывести <strong>взвешенный список категорий с подкатегориями</strong>. Это просто.<br />
<span id="more-204"></span></p>
<p>Есть таблица категорий, где category_title это название категории, category_id это ее номер в базе, parent_category_id это номер родительской категории (если он NULL &#8211; то категория сама является родительской) и weight это вес категории среди категорий ее уровня: </p>
<pre lang="sql">CREATE TABLE IF NOT EXISTS `category` (
  `category_id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_category_id` int(11) DEFAULT NULL,
  `title` varchar(250) NOT NULL,
  `weight` int(11) NOT NULL,
  PRIMARY KEY (`category_id`)
) ENGINE=MyISAM  COMMENT='shop categories' AUTO_INCREMENT=1;</pre>
<p>Создаем запрос который выводит категории и сразу сортирует их в правильном порядке:</p>
<pre lang="sql">
SELECT
    COALESCE( DC2.title, "" ) AS "parent_title",
    COALESCE( DC2.category_id, 0 ) AS "parent_category_id",
    DC2.weight AS "parent_weight",
    DC1.title AS "subcategory_title",
    DC1.category_id AS "subcategory_category_id",
    DC1.weight AS "subcategory_weight"
FROM `category` AS DC1
    LEFT OUTER JOIN `category` AS DC2
        ON DC1.parent_category_id = DC2.category_id
ORDER BY
    DC2.category_id ASC,
    DC2.weight DESC,
    DC1.weight DESC,
    DC2.title ASC,
    DC1.title ASC</pre>
<p>Как несложно заметить, если у записи из выдачи parent_category_id=0 то это родительская категория. Иначе это подкатегория с номером subcategory_id для категории с номером parent_category_id.</p>
<p>При выдаче категории сортируются так: сначала идут родительские категории, затем подкатегории отсортированные по весу и по алфавиту.</p>
<p>Далее, используя ваш любимый язык программирования, следует записать выдачу в ассоциативный массив, и загнать его в ваш любимый шаблонизатор.</p>
]]></content:encoded>
			<wfw:commentRss>http://byteflow.hackndev.org/blog/index.php/2008/12/sql-query-for-weighted-category-tree-with-subcategories/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
