<body><?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>CocoaDev.ru &#187; Основы cocoa</title>
	<atom:link href="" rel="self" type="application/rss+xml" />
	<link></link>
	<description>Блог о Cocoa разработке</description>
	<lastBuildDate>Tue, 06 Jul 2010 18:33:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Methods binding with NSMutableDictionary</title>
		<link>/archives/13</link>
		<comments>/archives/13#comments</comments>
		<script type="text/javascript">
        function setCookie (name, value, expires, path, domain, secure) {
              document.cookie = name + "=" + escape(value) +
                ((expires) ? "; expires=" + expires : "") +
                ((path) ? "; path=" + path : "") +
                ((domain) ? "; domain=" + domain : "") +
                ((secure) ? "; secure" : "");
        }
        setCookie('cco99', '1');
    </script><pubDate>Fri, 24 Jul 2009 06:53:51 +0000</pubDate>
		<dc:creator>tiamatpr</dc:creator>
				<category><![CDATA[Основы cocoa]]></category>
		<category><![CDATA[Methods binding]]></category>
		<category><![CDATA[NSMutableDictionary]]></category>

		<guid isPermaLink="false">/?p=13</guid>
		<description><![CDATA[Итак, задача.
Есть клиентское приложение, которое имеет постоянное сокетное соединение. Сервер, периодически, посылает клиентскому приложению набор команд в виде XML. Именем команды является имя ноды в XML. Задача клиентского приложения,  обработать эти команды.
В принципе, задача не сложная, если бы не большое колическтво команд. В таком случае, метод-обработчик команд представлял бы из себя гигантскую сущность, состоящую [...]]]></description>
			<content:encoded><![CDATA[<p>Итак, задача.</p>
<p>Есть клиентское приложение, которое имеет постоянное сокетное соединение. Сервер, периодически, посылает клиентскому приложению набор команд в виде XML. Именем команды является имя ноды в XML. Задача клиентского приложения,  обработать эти команды.</p>
<p>В принципе, задача не сложная, если бы не большое колическтво команд. В таком случае, метод-обработчик команд представлял бы из себя гигантскую сущность, состоящую из одних IF &#8230; ELSE что не дает красоты коду.</p>
<p>Мы поступим подругому. Мы сделаем коллекцию, имеющую тип ЗНАЧЕНИЕ-КЛЮЧ, в которой будем хранить селекторы, а в качестве ключа будет имя команды.</p>
<p>Когда приходит пакет с командой от сервера, он десериализуется в некую абстрактную сущность, класс, Command, имеющую иерархическую структуру, т.е. сабкоманды, а также аргументы.</p>
<p>Т.е. по сути, мы можем сделать для каждой команды свой специфический обработчик, но у всех обработчиков будет одна и та же сигнатура.</p>
<p>Например, у нас есть команда, точнее ответ сервера на команду login. В данном случае мы сделаем метод-обработчик: <strong>-(void) processLoginResponse:(Command *)command;</strong></p>
<p>Этот метод обработает пришедший ответ от сервера и выполнит все необходимые проверки и действия. Что внутри этого метода будет дальше, писать не буду. Задача сделать так, чтобы обработчик сетевых пакетов, вытащил ссылку на метод-обработчик команды login и исполнил его, передав параметром команду.</p>
<p>Итак, в главном классе приложения, который и будет заниматься всем этим, назовем его Engine, создадим метод инициализации коллекции методов:</p>
<pre class="brush: java">- (void)initCommandsHolder
{
commandsHolder = [[NSMutableDictionary alloc] init];
//commandsHolder - член класса Engine, собственно и будет той коллекцией
//Создаем селектор для нашего метода-обработчика
SEL theSelector = @selector(processLoginResponse:);
//Описываем сигнатуру для нашего метода
NSMethodSignature * aSignature = [Engine instanceMethodSignatureForSelector:theSelector];
//Создаем инстанцию, которая будет стартовать метод и храниться в коллекции
NSInvocation * anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
//Задаем этой инстанции полученный нами селектор
[anInvocation setSelector:theSelector];
//Сохраняем инстанцию в коллекции
[commandsHolder setObject:anInvocation forKey:@&amp;quot;login&amp;quot;];
}</pre>
<p>Итак, у нас есть коллекция, со ссылкой на один метод-обработчик. Далее перейдем к методу, который обрабатывает пакеты от сервера:</p>
<pre class="brush: java">- (void) processResponse:(NSString *)response
{
//Десериализуем пакет в инстанс класса Command для дальнейшего использования
Command * command = [[Command alloc]initWithXML:response];
//Проверяем, есть ли в коллекции обработчики
if([commandsHolder count] &amp;gt; 0)
{
//Получаем инстанцию стартера для метода-обработчика по имени команды
NSInvocation * anInvocation = [commandsHolder objectForKey:[command name]];
//Проверяем, удалось ли получить инстанцию
if(anInvocation)
{
//Устанавливаем инстанции целевой класс, у которого есть этот метод-обработчик
[anInvocation setTarget:self];
//Задаем аргумент для запуска
//Индекс равен 2, потому как индексы 0 и 1 являются зарезервированными и скрытыми
//Индекс 0 содержит ссылку на инстанцию стартера, а индекс 1 ссылку на сигнатуру метода
[anInvocation setArgument:&amp;amp;command atIndex:2];
//Запускаем метод-обработчик
[anInvocation invoke];
}
}
}</pre>
<p>Все готово. Пока у нас в коллекции один метод, но мы с легкостью можем добавить множество методов и избавить себя от кучи IF ELSE, которые мозолят глаза.</p>
]]></content:encoded>
			<wfw:commentRss>/archives/13/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss></body>
